Build Events Database

Fish

fish_events<-read_excel(path="/Users/eric/google_drive/MarineGEO/Fish/FISH_DATA_21Jul2017.xlsx",sheet="Events")
### Format events to schema
#change all empty columns from logical to character class
fish_events[sapply(fish_events, is.logical)] <- lapply(fish_events[sapply(fish_events, is.logical)],  as.character)
#change eventID to just the KANF value
fish_events$eventID<-str_extract(fish_events$eventID,"KANF\\d\\d\\d")
#round the lat/longs to four digits (~ 10m uncertainty)
fish_events$decimalLatitude<-round(as.numeric(fish_events$decimalLatitude),digits = 4)
fish_events$decimalLongitude<-round(as.numeric(fish_events$decimalLongitude),digits = 4)
fish_events$coordinateUncertaintyInMeters<-as.numeric(fish_events$coordinateUncertaintyInMeters) 
# class(fish_events$geoReferenceProtocol)
# class(fish_events$maximumDepthInMeters)
# class(fish_events$minimumDepthInMeters)
# class(fish_events$recordedBy) 
# class(fish_events$samplingProtocol) #some missing. ask Diane to fill this in
# class(fish_events$habitatBiotic)
#remove carriage returns from Geomorphological Zone
fish_events$habitatGeomorphologicalZone<-str_replace_all(fish_events$habitatGeomorphologicalZone,pattern="\r\n",replacement = "")
fish_events$habitatSubstrate<-str_replace_all(fish_events$habitatSubstrate,pattern="\r\n",replacement = "")
fish_events$year<-as.numeric(fish_events$year)
fish_events$month<-match(fish_events$month,month.abb)
fish_events$day<-as.numeric(fish_events$day)
#Recommended fields
# class(fish_events$eventRemarks)
# class(fish_events$locality)
# class(fish_events$eventRemarks)
# class(fish_events$verbatimCoordinates)
# class(fish_events$eventMedia)
#remove ending times from eventTime field
fish_events$eventTime<-str_extract(string=fish_events$eventTime,pattern="^\\d\\d:\\d\\d")

Algae

algae_events<-read_excel("/Users/eric/google_drive/MarineGEO/algae/MarineGEOHI_bioassessment_master_KANA.xlsx", sheet="Station")
### Format events to schema
#change all empty columns from logical to character class
algae_events[sapply(algae_events, is.logical)] <- lapply(algae_events[sapply(algae_events, is.logical)],  as.character)
#round to 4 decimal digits (~10m uncertainty) and meake sure longitude is negative
algae_events$decimalLatitude<-round(as.numeric(algae_events$decimalLatitude),digits = 4)
algae_events$decimalLongitude<-abs(round(as.numeric(algae_events$decimalLongitude),digits = 4))*-1
# class(algae_events$eventID)
# class(algae_events$geoReferenceProtocol) #good
# class(algae_events$coordinateUncertaintyInMeters) #good
# class(algae_events$maximumDepthInMeters) #some missing. ask Melinda to fill this in
# class(algae_events$minimumDepthInMeters)#some missing. ask Melinda to fill this in
# class(algae_events$recordedBy) #some missing. ask Melinda to fill this in
# class(algae_events$samplingProtocol) #some missing. ask Melinda to fill this in
# class(algae_events$`habitatBiotic`)
# class(algae_events$`habitatGeomorphologicalZone`)
# class(algae_events$`habitatSubstrate`)
#Recommended fields
# class(algae_events$eventRemarks)
# class(algae_events$locality)
# class(algae_events$eventRemarks)
# class(algae_events$verbatimCoordinates)
# class(algae_events$eventMedia)
#format time correctly
algae_events$eventTime<-as.character(parse_date_time(algae_events$eventTime, orders="ymdHMS", tz="HST"),format="%H:%M")

Macroinvertebrates

invert_events<-read_excel(path="/Users/eric/google_drive/MarineGEO/Inverts/BKANE_063017_FIMS.xlsx", sheet = "Station", skip=2)
### Format events to schema
# Note: invert event data need a lot of cleaning, including importing stations from the algae and meiofauna team, and making new stations with "A" or "B" appended. Currently 839 samples do not have station information because of this.
# remove event fields that don't appear in the schema
invert_events<-invert_events[,-grep(pattern = "^X",x = names(invert_events),perl=T)]
#change all empty columns from logical to character class
invert_events[sapply(invert_events, is.logical)] <- lapply(invert_events[sapply(invert_events, is.logical)],  as.character)
#round to 4 decimal digits (~10m uncertainty) and meake sure longitude is negative
invert_events$decimalLatitude<-round(as.numeric(invert_events$decimalLatitude),digits = 4)
invert_events$decimalLongitude<-abs(round(as.numeric(invert_events$decimalLongitude),digits = 4))*-1
invert_events$geoReferenceProtocol<-"GPS"
invert_events$coordinateUncertaintyInMeters<-100
# class(invert_events$maximumDepthInMeters) #some missing. ask John to fill this in
# class(invert_events$minimumDepthInMeters)#some missing. ask John to fill this in
#Format the date properly, get rid of the "raw" field
invert_events$day<-day(invert_events$eventDate)
invert_events$month<-month(invert_events$eventDate)
invert_events$year<-year(invert_events$eventDate)
invert_events$eventDate<-NULL
# class(invert_events$recordedBy) #good
# class(invert_events$samplingProtocol) #some missing. ask John to fill this in
# class(invert_events$habitatGeomorphologicalZone) #some missing. ask John to fill this in. #this needs to be aligned with the schema
# class(invert_events$habitatSubstrate) # some missing. ask John to fill this in. #this needs to be aligned with the schema
#Recommended fields
# class(invert_events$locality)
# class(invert_events$eventRemarks)

Meiofauna

meio_events<-read_excel(path="/Users/eric/google_drive/MarineGEO/Meiofauna/Hawaii2017_meiofauna_MarineGEO.xlsx", sheet = "station data", skip=1)
#remove columns that don't appear in MarineGEO schema
meio_events<-meio_events[,-grep(pattern = "^X",x = names(meio_events),perl=T)]
### Format events to schema
#Missing station KANM087!!!
#change all empty columns from logical to character class
meio_events[sapply(meio_events, is.logical)] <- lapply(meio_events[sapply(meio_events, is.logical)],  as.character)
#round to 4 decimal digits (~10m uncertainty) and meake sure longitude is negative
meio_events$decimalLatitude<-round(as.numeric(meio_events$decimalLatitude),digits = 4)
meio_events$decimalLongitude<-abs(round(as.numeric(meio_events$decimalLongitude),digits = 4))*-1
meio_events$coordinateUncertaintyInMeters<-100
meio_events$minimumDepthInMeters<-as.numeric(meio_events$minimumDepthInMeters)
meio_events$maximumDepthInMeters<-as.numeric(meio_events$maximumDepthInMeters)
# class(meio_events$maximumDepthInMeters)
# class(meio_events$minimumDepthInMeters)
# class(meio_events$recordedBy) #ask Freya to follow format - add last names, and pipes between names
# class(meio_events$samplingProtocol) #some missing. ask Freya to fill this in
# class(meio_events$habitatGeomorphologicalZone) #some missing. ask Freya to fill this in
# class(meio_events$habitatSubstrate) # some missing. ask Freya to fill this in
# class(meio_events$habitatBiotic)
#Recommended fields
# class(meio_events$locality)
# class(meio_events$eventRemarks)
meio_events$day<-day(meio_events$eventDate)
meio_events$month<-month(meio_events$eventDate)
meio_events$year<-year(meio_events$eventDate)
meio_events$eventDate<-NULL
#format the $^#&* time correctly
meio_events$eventTime<-format(.POSIXct(86400*as.numeric(meio_events$eventTime), "UTC"), "%H:%M")
#meio_events$eventTime<-as.character(parse_date_time(meio_events$eventTime, orders="ymdHMS", tz="HST"),format="%H:%M")
meio_events$eventMedia<-"N"

ARMS

arms_events<-read_excel(path="/Users/eric/google_drive/MarineGEO/ARMS/MarineGEOHI_bioassessment_master-ARMS.xlsx", sheet = "Station")
### Format events to schema
#change all empty columns from logical to character class
arms_events[sapply(arms_events, is.logical)] <- lapply(arms_events[sapply(arms_events, is.logical)],  as.character)
#round to 4 decimal digits (~10m uncertainty) and meake sure longitude is negative
arms_events$decimalLatitude<-round(as.numeric(arms_events$decimalLatitude),digits = 4)
arms_events$decimalLongitude<-abs(round(as.numeric(arms_events$decimalLongitude),digits = 4))*-1
arms_events$coordinateUncertaintyInMeters<-10
arms_events$minimumDepthInMeters<-as.numeric(arms_events$minimumDepthInMeters)
# class(arms_events$geoReferenceProtocol)
# class(arms_events$eventID)
# class(arms_events$maximumDepthInMeters)
# class(arms_events$recordedBy) #ask Laetitia to follow name format
# class(arms_events$samplingProtocol)
# class(arms_events$habitatGeomorphologicalZone)
# class(arms_events$habitatSubstrate) 
# class(arms_events$habitatBiotic)
#Recommended fields
# class(arms_events$locality)
# class(arms_events$year)
# class(arms_events$month)
# class(arms_events$day)
arms_events$eventMedia<-"Y" #still need to get these from Laetitia

Visual Transects

trans_events<-read_excel(path="/Users/eric/google_drive/MarineGEO/Transects/bioassessment_KANV.xlsx", sheet = "Station")
trans_event_photos<-read_excel(path="/Users/eric/google_drive/MarineGEO/Transects/KANV_benthic-photos_filenames_20170711.xlsx", sheet = "Sheet1")
# event photos
#pop off the eventID into its own field
trans_event_photos$eventID<-sub(pattern="(KANV\\d\\d\\d)_.+",replacement = "\\1", trans_event_photos$eventMedia, perl=T)
#use ddply to lump all eventMedia into a single field, separated by a |
trans_eventMedia<-ddply(trans_event_photos, "eventID", transform, eventMedia = paste(eventMedia, collapse = "|"))
#keep only the first instance of each occurrenceID
trans_eventMedia<-trans_eventMedia[!duplicated(trans_eventMedia$eventID),]
#delete original eventMedia column and join on the new one
trans_events$eventMedia<-NULL
trans_events<-left_join(trans_events, trans_eventMedia, by="eventID")
### Format events to schema
#change all empty columns from logical to character class
trans_events[sapply(trans_events, is.logical)] <- lapply(trans_events[sapply(trans_events, is.logical)],  as.character)
#round to 4 decimal digits (~10m uncertainty) and meake sure longitude is negative
trans_events$decimalLatitude<-round(as.numeric(trans_events$decimalLatitude),digits = 4)
trans_events$decimalLongitude<-abs(round(as.numeric(trans_events$decimalLongitude),digits = 4))*-1
trans_events$minimumDepthInMeters<-as.numeric(trans_events$minimumDepthInMeters)
# class(trans_events$eventID)
# class(trans_events$coordinateUncertaintyInMeters)
# class(trans_events$maximumDepthInMeters)
# class(trans_events$recordedBy) 
# class(trans_events$samplingProtocol)
# class(trans_events$habitatGeomorphologicalZone)
# class(trans_events$habitatSubstrate)
# class(trans_events$habitatBiotic)
#Recommended fields
# class(trans_events$locality)
# class(trans_events$year)
# class(trans_events$month)
# class(trans_events$day)
trans_events$eventMedia<-"Y"
trans_events$eventTime<-as.character(parse_date_time(trans_events$eventTime, orders="ymdHMS", tz="HST"),format="%H:%M")

Join Events

events<-full_join(fish_events,algae_events)
events<-full_join(events,invert_events)
events<-full_join(events,meio_events)
events<-full_join(events,arms_events)
events<-full_join(events,trans_events)

Build sample databases

Fish

Import

# First go through and make sure all stations have Lat/Longs, or as many as possible. Delete secondary lat/longs
#read in the sample data, skipping first 3 lines of other headers. Format all times as hh:mm in Excel, paste into textwrangler if they need homogenization (i.e. multiple formats of times)
fish_samples<-read_excel(path="/Users/eric/google_drive/MarineGEO/Fish/FISH_DATA_21Jul2017.xlsx",sheet="Samples")
fish_genetic<-read_excel(path="/Users/eric/google_drive/MarineGEO/Fish/FISH_DATA_21Jul2017.xlsx",sheet="Genetic samples")
#these commands apply to the original fish-group template
#remove columns without mapped DwC terms mapped
#fish_samples<-fish_samples[,-grep(pattern = "^X",x = names(fish_samples),perl=T)]
#fish_events<-fish_events[,-grep(pattern = "^X",x = names(fish_events),perl=T)]
#remove records without occurrenceIDs (temp before final dataset)
#fish_samples<-fish_samples[-which(is.na(fish_samples$occurrenceID)),]
#translate fieldIDs to eventIDs
#fish_samples$eventID<-gsub("LRP 17-","KANF0",fish_samples$eventID)
#use ddply to lump all materialSampleIDs into a single field, separated by a |
#fish_samples<-ddply(fish_samples, "occurrenceID", transform, materialSampleID = #paste(materialSampleID, collapse = "|"))
#keep only the first instance of each occurrenceID
#fish_samples<-fish_samples[!duplicated(fish_samples$occurrenceID),]

Format samples to schema

#change all empty columns from logical to character class
fish_samples[sapply(fish_samples, is.logical)] <- lapply(fish_samples[sapply(fish_samples, is.logical)],  as.character)
#Fix the eventIDs
fish_samples$eventID<-str_extract(fish_samples$eventID,"KANF\\d\\d\\d")
fish_samples$otherCatalogNumbers<-NULL # drop this for now - it will be replaced by fish_biorep below
# class(fish_samples[,which(sapply(fish_samples, is.logical))])<-"character"
# class(fish_samples$occurrenceID)
# class(fish_samples$basisofRecord)
# class(fish_samples$catalogNumber)<-"character"
# class(fish_samples$organismScope)
# class(fish_samples$eventID)
# class(fish_samples$scientificName) #eventually parse this into taxon categories?
# class(fish_samples$taxonRank) #using this
# class(fish_samples$individualCount)
# class(fish_samples$institutionID)
# make identifiedBy go firstname lastname
fish_samples$identifiedBy<-str_replace(fish_samples$identifiedBy, pattern="(\\w+), (.+)", replacement="\\2 \\1")
fish_samples$catalogNumber<-as.character(fish_samples$catalogNumber)

Format the biorepository info

colnames(fish_genetic)[5]<-"BiorepositoryID"
colnames(fish_genetic)[6]<-"tissueNotes"
colnames(fish_genetic)[2]<-"occurrenceID"
#use ddply to lump all materialSampleIDs into a single field, separated by a |
fish_biorep<-ddply(fish_genetic, "occurrenceID", transform, otherCatalogNumbers = paste(BiorepositoryID, collapse = "|"), tissueNotes = paste(tissueNotes, collapse="|"))
#keep only the first instance of each occurrenceID
fish_biorep<-fish_biorep[!duplicated(fish_biorep$otherCatalogNumbers),]
fish_biorep$otherCatalogNumbers<-as.character(fish_biorep$otherCatalogNumbers)

Join the event data onto the occurrence data

#first join the biorep numbers to this data
fish_samples<-left_join(fish_samples,fish_biorep[,c(2,6,7)],by="occurrenceID")
#now join samples and events
fish<-left_join(fish_samples,events,by="eventID")

Make a Map

#optionally make it from the points provided
#bbox<-make_bbox(lon=fish2$decimalLongitude,lat=fish2$decimalLatitude)
#by individual
fish2<-fish %>% group_by(decimalLatitude, decimalLongitude) %>% summarize(count=n()) 
#by species
fish3 <- fish %>% group_by(scientificName, decimalLatitude, decimalLongitude) %>% summarize(count=n())
#richness
fish4<-fish3 %>% group_by(decimalLatitude,decimalLongitude) %>% summarize(richness=n())
fish6<-left_join(fish2,fish4)
fish_map<-ggmap(dmap) + geom_point(data = fish6, mapping = aes(x = decimalLongitude, y = decimalLatitude, size=count, color=richness)) + scale_color_gradient(low = "green", high="red") + guides(color=guide_colorbar(title="Species Richness",), size=guide_legend(title="Individual Count")) + theme(axis.title=element_blank())
fish_map
ggsave(fish_map,filename="./output/fish_map.pdf")

Algae

Import

#edit eventIDs for capitalization
algae_samples<-read_excel("/Users/eric/google_drive/MarineGEO/algae/MarineGEOHI_bioassessment_master_KANA.xlsx", sheet="Sample")

Format samples to schema

#change all empty columns from logical to character class
algae_samples[sapply(algae_samples, is.logical)] <- lapply(algae_samples[sapply(algae_samples, is.logical)],  as.character)
# class(algae_samples$occurrenceID)
# class(algae_samples$catalogNumber)
# class(algae_samples$otherCatalogNumbers)
# class(algae_samples$organismScope)
# class(algae_samples$eventID)
# class(algae_samples$scientificName) #eventually parse this into taxon categories?
# class(algae_samples$taxonRank) # Melinda needs to populate this...
# class(algae_samples$identifiedBy)
# class(algae_samples$individualCount)
algae_samples$basisofRecord<-"specimen"
algae_samples$institutionID<-"USNM"

Join the event data onto the occurrence data

algae<-left_join(algae_samples,events,by="eventID")

Make A Map

#by individual
algae2<-algae %>% group_by(decimalLatitude, decimalLongitude) %>% summarize(count=n()) 
#by species
algae3 <- algae[-which(algae$scientificName=="?"),] %>% group_by(scientificName, decimalLatitude, decimalLongitude) %>% summarize(count=n())
#richness
algae4<-algae3 %>% group_by(decimalLatitude,decimalLongitude) %>% summarize(richness=n())
algae5<-left_join(algae2,algae4)
#algae5<-algae5[which(is.na(algae5$decimalLatitude)),]
#algae5<-algae5[-which(algae5$scientificName=="?"),]
algae5[4,4]<-1
algae5[11,4]<-2
extra<-algae5[33,]
algae5<-algae5[-33,] #remove outlier
algae_map<-ggmap(dmap) + geom_point(data = algae5, mapping = aes(x = decimalLongitude, y = decimalLatitude, size=count, color=richness)) + scale_color_gradient(low = "green", high="red") + guides(color=guide_colorbar(title="Type Richness",), size=guide_legend(title="Individual Count")) + theme(axis.title=element_blank()) + geom_point(data=extra, mapping=aes(x = decimalLongitude, y = decimalLatitude, size=30, color=30))
#add outlier back in as a red dot size=30
algae_map
ggsave(algae_map,filename="./output/algae_map.pdf")

Macroinvertebrates

Import

invert_samples<-read_excel(path="/Users/eric/google_drive/MarineGEO/Inverts/BKANE_063017_FIMS.xlsx", sheet = "Specimen",skip=3)
#sponges will be loaded here, cleaned up, and then joined with the rest of the inverts
sponge_samples<-read_excel(path="/Users/eric/google_drive/MarineGEO/Sponges/VICENTE_BIOBLITZ2017_SPONGEMETADATA_FIMS.xlsx", sheet = "Sheet1",skip=1)
#remove columns that don't appear in MarineGEO schema
invert_samples<-invert_samples[,-grep(pattern = "^X",x = names(invert_samples),perl=T)]
sponge_samples<-sponge_samples[,-grep(pattern = "^X",x = names(sponge_samples),perl=T)]
#remove records without occurrenceIDs (temp before final dataset)
invert_samples<-invert_samples[-which(is.na(invert_samples$scientificName)),]
sponge_samples<-sponge_samples[-which(is.na(sponge_samples$scientificName)),]
#change all empty columns from logical to character class
invert_samples[sapply(invert_samples, is.logical)] <- lapply(invert_samples[sapply(invert_samples, is.logical)],  as.character)
sponge_samples[sapply(sponge_samples, is.logical)] <- lapply(sponge_samples[sapply(sponge_samples, is.logical)],  as.character)
sponge_samples$phylum[which(is.na(sponge_samples$phylum))]<-"Porifera"
sponge_samples$eventID<-str_replace(sponge_samples$eventID,pattern="-", replacement="")
invert_samples<-full_join(invert_samples,sponge_samples)

Taxonomize

This code will populate taxonRank with the lowest known taxonomic category

invert_samples$taxonRank[which(!is.na(invert_samples$phylum))]<-"phylum"
invert_samples$taxonRank[which(!is.na(invert_samples$class))]<-"class"
invert_samples$taxonRank[which(!is.na(invert_samples$subclass))]<-"subclass"
invert_samples$taxonRank[which(!is.na(invert_samples$order))]<-"order"
invert_samples$taxonRank[which(!is.na(invert_samples$suborder))]<-"suborder"
invert_samples$taxonRank[which(!is.na(invert_samples$superfamily))]<-"superfamily"
invert_samples$taxonRank[which(!is.na(invert_samples$family))]<-"family"
invert_samples$taxonRank[which(!is.na(invert_samples$subfamily))]<-"subfamily"
invert_samples$taxonRank[which(!is.na(invert_samples$genus))]<-"genus"
invert_samples$taxonRank[which(!is.na(invert_samples$species))]<-"species"
invert_samples$taxonRank[grep("sp\\.",invert_samples$species)]<-"genus"

Format samples to schema

str_replace(string=invert_samples$eventID, pattern="(KAN\\w\\d\\d\\d)[A-Z]",replacement="\\1")
   [1] "KANI001"       "KANI001"       "KANI001"       "KANI001"       "KANI001"      
   [6] "KANI001"       "KANI001"       "KANI001"       "KANI001"       "KANI001"      
  [11] "KANI001"       "KANI001"       "KANI005"       "KANI005"       "KANI001"      
  [16] "KANI001"       "KANI001"       "KANI001"       "KANI001"       "KANI001"      
  [21] "KANI001"       "KANI001"       "KANI001"       "KANI001"       "KANI001"      
  [26] "KANI001"       "KANI001"       "KANI006"       "KANI001"       "KANI001"      
  [31] "KANI001"       "KANI005"       "KANI005"       "KANI005"       "KANI001"      
  [36] "KANI006"       "KANI006"       "KANI006"       "KANI005"       "KANI006"      
  [41] "KANI006"       "KANI006"       "KANI006"       "KANI001"       "KANI006"      
  [46] "KANI006"       "KANI006"       "KANI006"       "KANI005"       "KANI006"      
  [51] "KANI005"       "KANI006"       "KANI006"       "KANI003"       "KANI003"      
  [56] "KANF"          "KANI006"       "KANI006"       "KANI006"       "KANI006"      
  [61] "KANI004"       "KANI004"       "KANI004"       "KANI004"       "KANI004"      
  [66] "KANI004"       "KANI013"       "KANI013"       "KANI013"       "KANI013"      
  [71] "KANI012"       "KANI012"       "KANI012"       "KANI012"       "KANI012"      
  [76] "KANI012"       "KANI013"       "KANI017"       "KANI017"       "KANI017"      
  [81] "KANI017"       "KANI019"       "KANI019"       "KANI019"       "KANI019"      
  [86] "KANI019"       "KANI019"       "KANI019"       "KANI021"       "KANI021"      
  [91] "KANI020"       "KANI024"       "KANI024"       "KANI027"       "KANI028"      
  [96] "KANI001"       "KANI027"       "KANI028"       "KANI029"       "KANI029"      
 [101] "KANI027"       "KANI028"       "KANI027"       "KANI028"       "KANI028"      
 [106] "KANI028"       "KANI033"       "KANI033"       "KANI033"       "KANI033"      
 [111] "KANI033"       "KANI037"       "KANI033"       "KANI033"       "KANI039"      
 [116] "KANI041"       "KANI043"       "KANI041"       "KANI041"       "KANI049"      
 [121] "KANA001"       "KANI004"       "KANI008"       "KANI008"       "KANI008"      
 [126] "KANI008"       "KANI006"       "KANI003"       "KANI006"       "KANI006"      
 [131] "KANI006"       "KANI005"       "KANI005"       "KANI008"       "KANI006"      
 [136] "KANI006"       "KANI006"       "KANI006"       "KANI006"       "KANI006"      
 [141] "KANM003"       "KANI006"       "KANI007"       "KANI007"       "KANI004"      
 [146] "KANI009"       "KANI009"       "KANI007"       "KANI007"       "KANI007"      
 [151] "KANI009"       "KANI009"       "KANI009"       "KANI004"       "KANI004"      
 [156] "KANI009"       "KANI009"       "KANI004"       "KANI004"       "KANI004"      
 [161] "KANI004"       "KANI004"       "KANI004"       "KANI004"       "KANI004"      
 [166] "KANI004"       "KANI004"       "KANI004"       "KANI004"       "KANI004"      
 [171] "KANI001"       "KANI004"       "KANI004"       "KANI004"       "KANI004"      
 [176] "KANI004"       "KANI004"       "KANI004"       "KANI009"       "KANI009"      
 [181] "KANI009"       "KANI004"       "KANI009"       "KANI009"       "KANI009"      
 [186] "KANI009"       "KANI009"       "KANI009"       "KANI009"       "KANI009"      
 [191] "KANI009"       "KANI004"       "KANI004"       "KANI004"       "KANI004"      
 [196] "KANI004"       "KANI004"       "KANI004"       "KANI004"       "KANI004"      
 [201] "KANI004"       "KANI004"       "KANI004"       "KANI004"       "KANI004"      
 [206] "KANI004"       "KANI004"       "KANI004"       "KANI004"       "KANI004"      
 [211] "KANI004"       "KANI004"       "KANI004"       "KANI004"       "KANI010"      
 [216] "KANI010"       "KANI010"       "KANI010"       "KANI010"       "KANI011"      
 [221] "KANI010"       "KANI004"       "KANI004"       "KANI004"       "KANI013"      
 [226] "KANI013"       "KANI012"       "KANI012"       "KANI012"       "KANI012"      
 [231] NA              "KANI012"       "KANI012"       "KANI012"       "KANI012"      
 [236] "KANI012"       "KANI012"       "KANI012"       "KANI004"       "KANI004"      
 [241] "KANI012"       "KANI012"       "KANI013"       "KANI004"       "KANI004"      
 [246] "KANM007"       "KANM023"       "KANI004"       "KANI004"       "KANI004"      
 [251] "KANI004"       "KANI004"       "KANI004"       "KANI004"       "KANI004"      
 [256] "KANI013"       "KANI013"       "KANI015"       "KANI006"       "KANI004"      
 [261] "KANI013"       "KANI013"       "KANI013"       "KANI013"       "KANI013"      
 [266] "KANI013"       "KANI013"       "KANI013"       "KANI013"       NA             
 [271] "KANI002"       "KANI002"       "KANI001"       "KANI002"       "KANI002"      
 [276] "KANI002"       "KANI002"       "KANI002"       "KANI013"       "KANI013"      
 [281] "KANI013"       "KANA006"       "KANA006"       "KANA006"       "KANA006"      
 [286] "KANI001"       "KANI001"       "KANI013"       "KANI013"       "KANI004"      
 [291] "KANI013"       "KANI015"       "KANI015"       "KANI015"       "KANI015"      
 [296] "KANI015"       "KANI015"       "KANI013"       "KANI015"       "KANI013"      
 [301] "KANI001"       "KANI018"       "KANI019"       "KANI024"       "KANI022"      
 [306] "KANI035"       "KANI034"       "KANI037"       "KANI035"       "KANI034"      
 [311] "KANI043"       NA              "KANI046"       "KANI050"       "KANI048"      
 [316] "KANI060"       "KANI060"       "KANI055"       "KANI060"       "KANI060"      
 [321] "KANI055"       "KANI055"       "KANI066"       NA              "KANI076"      
 [326] "KANI076"       NA              NA              "KANI013"       "KANI013"      
 [331] "KANI013"       "KANI013"       "KANI013"       "KANI013"       "KANI013"      
 [336] "KANI013"       "KANI013"       "KANI013"       "KANI013"       "KANI013"      
 [341] "KANI015"       "KANI013"       "KANI013"       "KANI015"       "KANI015"      
 [346] "KANI015"       "KANI015"       "KANI015"       "KANI015"       "KANI015"      
 [351] "KANI015"       "KANI015"       "KANI015"       "KANI015"       "KANI015"      
 [356] "KANI012"       "KANI012"       "KANI014"       "KANI014"       "KANI013"      
 [361] "KANI013"       "KANI013"       "KANI013"       "KANI013"       "KANI013"      
 [366] "KANI014"       "KANI014"       "KANI014"       "KANI013"       "KANI015"      
 [371] "KANI015"       "KANI015"       "KANI015"       "KANI015"       "KANI015"      
 [376] "KANI015"       "KANI015"       "KANI015"       "KANI015"       "KANI015"      
 [381] "KANI015"       "KANI015"       "KANI015"       "KANI015"       "KANI015"      
 [386] "KANI015"       "KANI015"       "KANI015"       "KANI015"       "KANI015"      
 [391] "KANI016"       "KANI016"       "KANI016"       "KANI016"       "KANI016"      
 [396] "KANI016"       "KANI016"       "KANI016"       "KANI016"       "KANI016"      
 [401] "KANI016"       "KANI016"       "KANI016"       "KANI016"       "KANI016"      
 [406] "KANI015"       "KANI016"       "KANI016"       "KANI016"       "KANI016"      
 [411] "KANI016"       "KANI016"       "KANI016"       "KANI016"       "KANI016"      
 [416] "KANI016"       "KANI016"       "KANI016"       "KANI016"       "KANI016"      
 [421] "KANI016"       "KANI016"       "KANI016"       "KANI016"       "KANI016"      
 [426] "KANI016"       NA              "KANI015"       "KANI013"       "KANI016"      
 [431] "KANI016"       "KANI016"       "KANI013"       "KANI001"       "KANI015"      
 [436] "KANI016"       "KANI013"       "KANI013"       "KANI004"       "KANI004"      
 [441] "KANM020"       "KANM020"       "KANM020"       "KANM020"       "KANM008"      
 [446] "KANM008"       "KANM008"       "KANI016"       "KANI018"       "KANI018"      
 [451] "KANI018"       "KANI018"       "KANI018"       "KANI018"       "KANI018"      
 [456] "KANM020"       "KANM020"       "KANI017"       "KANI018"       "KANM020"      
 [461] "KANM020"       "KANI017"       "KANI017"       "KANI017"       "KANI017"      
 [466] "KANI017"       "KANI017"       "KANI017"       "KANI018"       "KANI017"      
 [471] "KANI019"       "KANI019"       "KANI019"       "KANI019"       "KANI019"      
 [476] "KANI019"       "KANI019"       "KANI016"       "KANI017"       "KANI017"      
 [481] "KANI017"       "KANI017"       "KANI017"       "KANI017"       "KANI017"      
 [486] "KANI017"       "KANI017"       "KANI017"       "KANI017"       "5/24 am ?"    
 [491] "KANI019"       "KANI019"       "KANI017"       "KANI017"       "KANI018"      
 [496] "KANI017"       "KANI017"       "KANI017"       "KANI017"       "KANI017"      
 [501] "KANI017"       "KANI017"       "KANI017"       "KANI017"       "KANI017"      
 [506] "KANI017"       "KANI017"       "KANI017"       "KANI019"       "KANI017"      
 [511] "KANI017"       "KANI017"       "KANI017"       "KANI019"       "KANI017"      
 [516] "KANI019"       "KANI019"       "KANI019"       "KANI019"       "KANI019"      
 [521] "KANI019"       "KANI019"       "KANI019"       "KANI019"       "KANI019"      
 [526] "KANI019"       "KANI019"       "KANI019"       "KANI019"       "KANI019"      
 [531] "KANI019"       "KANI019"       "KANI019"       "KANI019"       "KANI019"      
 [536] "KANI019"       "KANI019"       "KANI019"       "KANI019"       "KANI019"      
 [541] "KANI019"       "KANI019"       "KANI018"       "KANI019"       "KANI019"      
 [546] "KANI019"       "KANI019"       "KANI019"       "KANI017"       "KANI017"      
 [551] "KANI017"       "KANI017"       "KANI017"       "KANI017"       "KANI017"      
 [556] "KANI017"       "KANI017"       "KANI017"       "KANI017"       "KANI017"      
 [561] "KANI017"       "KANI017"       "KANI017"       "KANI017"       "KANI019"      
 [566] "KANI017"       "KANI018"       "KANI014"       "KANI019"       "KANI019"      
 [571] "KANI019"       "T19"           "T19"           "KANI019"       "KANI019"      
 [576] "KANI019"       "KANI019"       "KANI019"       "KANI020"       "KANI020"      
 [581] "KANI020"       "KANI020"       "KANI019"       "KANI019"       "KANI019"      
 [586] "KANI022"       "KANI022"       "KANI022"       "KANI022"       "KANI022"      
 [591] "KANI022"       "KANA016"       "KANA016"       "KANA016"       "KANI022"      
 [596] "KANI022"       "KANI022"       "KANI022"       "KANI022"       "KANI022"      
 [601] "KANI022"       "MXW002"        "MXW002"        "MXW002"        "MXW002"       
 [606] "MXW001"        "MXW001 or 002" "MXW001 or 002" "KANI020"       "KANI020"      
 [611] "KANI020"       "KANI020"       "KANI020"       "KANI020"       "KANI020"      
 [616] "KANI020"       "KANI020"       "KANI020"       "KANI020"       "KANI020"      
 [621] "KANI020"       "KANI020"       "KANI020"       "KANI020"       "KANI020"      
 [626] "KANI022"       "KANI020"       "KANI020"       "KANI022"       "KANI019"      
 [631] "KANI019"       "KANI019"       "KANI019"       "KANI019"       "KANI020"      
 [636] "KANI020"       "KANM031"       "KANI023"       "KANI023"       "KANI022"      
 [641] "KANI020"       "KANI020"       "KANI020"       "KANI020"       "KANI023"      
 [646] "KANI023"       "KANI023"       "KANI023"       "KANI023"       "KANA016"      
 [651] "KANA016"       "KANI022"       "KANI022"       "KANI022"       "KANI022"      
 [656] "KANI022"       "KANI022"       "KANI021"       "KANI021"       "KANI021"      
 [661] "KANI021"       "KANI024"       "KANI021"       "KANI022"       "KANI021"      
 [666] "KANI021"       "KANI024"       "KANI019"       "KANI024"       "KANI024"      
 [671] "KANI019"       "KANI022"       "KANM031"       "KANI024"       "KANI019"      
 [676] "KANI019"       "KANI019"       "KANI024"       "KANI024"       "KANI019"      
 [681] "KANI019"       "KANI022"       "KANI022"       "KANI019"       "KANI019"      
 [686] "KANI019"       "KANI024"       "KANI022"       "KANI022"       "KANI022"      
 [691] "KANI022"       "KANI022"       "KANI024"       "KANI024"       "KANI022"      
 [696] "KANI022"       "KANI022"       "KANI022"       "KANI021"       "KANI022"      
 [701] "KANI022"       "KANI024"       "KANI024"       "KANI024"       "KANI022"      
 [706] "KANI022"       "KANI022"       "KANI022"       "KANI022"       "KANI022"      
 [711] "KANI022"       "KANI022"       "KANI022"       "KANI022"       "KANI022"      
 [716] "KANI022"       "KANI022"       "KANI022"       "KANI022"       "KANI024"      
 [721] "KANI024"       "KANI024"       "KANI022"       "KANI022"       "KANI022"      
 [726] "KANI022"       "KANI022"       "KANI022"       "KANI024"       "KANI022"      
 [731] "KANI024"       "KANI024"       "KANI022"       "KANI022"       "KANI024"      
 [736] "KANI024"       "KANI024"       "KANI024"       "KANI024"       "KANI024"      
 [741] "KANI024"       "KANI024"       "KANI024"       "KANI024"       "KANI024"      
 [746] "KANI024"       "KANI024"       "KANI024"       "KANI024"       "KANI024"      
 [751] "KANI024"       "KANI024"       "KANI024"       "KANI024"       "KANI024"      
 [756] "KANI024"       "KANI024"       "KANI024"       "KANI024"       "KANI024"      
 [761] "KANI024"       "KANI024"       "KANI024"       "KANI024"       "KANI024"      
 [766] "KANI024"       "KANI024"       "KANI024"       "KANI022"       "KANI024"      
 [771] "KANI023"       "KANI023"       "KANI014"       "KANI014"       "KANI014"      
 [776] "KANI014"       "KANI014"       "KANI022"       "KANI019"       "KANI019"      
 [781] "KANI019"       "KANI019"       "KANI019"       "KANI019"       "KANI019"      
 [786] "KANI019"       "KANI019"       "KANI019"       "KANI019"       "KANI019"      
 [791] "KANI019"       "KANI024"       "KANI024"       "KANI024"       "KANI024"      
 [796] "KANI019"       "KANI019"       "KANI025"       "KANM037"       "KANI027"      
 [801] "KANI027"       "KANI027"       "KANI027"       "KANI027"       "KANI027"      
 [806] "KANI027"       "KANI027"       "KANI027"       "KANI027"       "KANI027"      
 [811] "KANI027"       "KANI027"       "KANI027"       "KANI027"       "KANI027"      
 [816] "KANI027"       "KANI027"       "KANI027"       "KANI027"       "KANI027"      
 [821] "KANI001"       "KANI027"       "KANI027"       "KANI027"       "KANI027"      
 [826] "KANI027"       "KANI027"       "KANI027"       "KANI027"       "KANI027"      
 [831] "KANA025"       "KANA025"       "KANA025"       "KANI029"       "KANI029"      
 [836] "KANI029"       "KANI029"       "KANI029"       "KANI029"       "KANI029"      
 [841] "KANI028"       "KANI028"       "KANI028"       "KANI028"       "KANI028"      
 [846] "KANI028"       "KANI028"       "KANI029"       "KANI029"       "KANBZ001"     
 [851] "KANBZ002"      "KANBZ003"      "KANBZ004"      "KANBZ005"      "KANBZ006"     
 [856] "KANBZ007"      "KANBZ008"      "KANBZ008"      "KANBZ010"      "KANBZ013"     
 [861] "KANBZ014"      "KANI001"       "KANI031"       "MXW003"        "MXW003"       
 [866] "KANI025"       "KANI025"       "KANI001"       "KANI024"       "KANI028"      
 [871] "KANI032"       "KANI032"       "KANI032"       "KANI032"       "KANI032"      
 [876] "KANI032"       "KANI032"       "KANI032"       "KANI032"       "KANI032"      
 [881] "KANF019"       "KANF019"       "KANF019"       "KANF019"       "KANI032"      
 [886] "KANI001"       "KANI030"       "KANI030"       "KANI030"       "KANI028"      
 [891] "KANI029"       "KANI029"       "KANI029"       "KANI029"       "KANI029"      
 [896] "KANI030"       "KANI027"       "KANI027"       "KANI030"       "KANI027"      
 [901] "KANI027"       "KANI027"       "KANI027"       "KANI027"       "KANI027"      
 [906] "KANI027"       "KANI027"       "KANI027"       "KANI027"       "KANI027"      
 [911] "KANI027"       "KANI027"       "KANI027"       "KANI030"       "KANI028"      
 [916] "KANI030"       "KANI030"       "KANI027"       "KANI024"       "KANI024"      
 [921] "KANI024"       "KANI024"       "KANI024"       "KANI024"       "KANI022"      
 [926] "KANI022"       "KANI022"       "KANI022"       "KANI022"       "KANI022"      
 [931] "KANI030"       "KANI030"       "KANI024"       "KANI024"       "KANI024"      
 [936] "KANI022"       "KANI022"       "KANI030"       "KANI030"       "KANI030"      
 [941] "KANI030"       "KANI030"       "KANI030"       "KANI030"       "KANI030"      
 [946] "KANI030"       "KANI030"       "KANI030"       "KANI030"       "KANI025"      
 [951] "KANI025"       "KANI025"       "KANI025"       "KANI001"       "KANI035"      
 [956] "KANI035"       "KANI035"       "KANI035"       "KANI035"       "KANI035"      
 [961] "KANI035"       "KANI034"       "KANI034"       "KANI034"       "KANI034"      
 [966] "KANI034"       "KANI034"       "KANI034"       "KANI030"       "KANI030"      
 [971] "KANI030"       "KANI033"       "KANI033"       "KANI000"       "KANI037"      
 [976] "KANI037"       "KANI037"       "KANI037"       "KANI021"       "KANI021"      
 [981] "KANI021"       "KANI021"       "KANI019"       "KANI021"       "KANI021"      
 [986] "KANI021"       "KANI021"       "KANI021"       "KANI021"       "KANI021"      
 [991] "KANI023"       "KANI023"       "KANI023"       "KANI023"       "KANI023"      
 [996] "KANI023"       "KANI023"       "KANI022"       "KANI023"       "KANI029"      
 [ reached getOption("max.print") -- omitted 1488 entries ]

Join the event data onto the occurrence data

invert<-left_join(invert_samples,events,by="eventID")

Make A Map

#by individual
invert2<-invert %>% group_by(decimalLatitude, decimalLongitude) %>% summarize(individualCount=sum(individualCount,na.rm = T)) 
#by species
invert3 <- invert %>% group_by(scientificName, decimalLatitude, decimalLongitude) %>% summarize(count=n())
#richness
invert4<-invert3 %>% group_by(decimalLatitude,decimalLongitude) %>% summarize(richness=n())
invert5<-left_join(invert2,invert4)
invert_map<-ggmap(dmap) + geom_point(data = invert5[-c(length(invert5$richness)-1,length(invert5$richness)),], mapping = aes(x = decimalLongitude, y = decimalLatitude, size=individualCount, color=richness)) + scale_color_gradient(low = "green", high="red") + guides(color=guide_colorbar(title="Type Richness",), size=guide_legend(title="Individual Count")) + theme(axis.title=element_blank()) 
invert_map
ggsave(invert_map,filename="./output/invert_map.pdf")

#create a vector of the eventIDs not finding a match in the events database
bad_eventIDs<-invert$eventID[which(is.na(invert$decimalLatitude))]

Make A Sponge Map

sponge<-invert[which(invert$phylum=="Porifera"),]
#by individual
sponge2<-sponge %>% group_by(decimalLatitude, decimalLongitude) %>% summarize(individualCount=sum(individualCount,na.rm = T)) 
#by species
sponge3 <- sponge %>% group_by(scientificName, decimalLatitude, decimalLongitude) %>% summarize(count=n())
#richness
sponge4<-sponge3 %>% group_by(decimalLatitude,decimalLongitude) %>% summarize(richness=n())
sponge5<-left_join(sponge2,sponge4)
sponge_map<-ggmap(dmap) + geom_point(data = sponge5[-c(61,62),], mapping = aes(x = decimalLongitude, y = decimalLatitude, size=individualCount, color=richness)) + scale_color_gradient(low = "green", high="red") + guides(color=guide_colorbar(title="Type Richness",), size=guide_legend(title="Individual Count")) + theme(axis.title=element_blank()) 
sponge_map
ggsave(sponge_map,filename="./output/sponge_map.pdf")

Meiofauna

Import

#note meio data still need some cleaning, including importing some stations from inverts and fish, and fixing up eventIDs to have 3 digits instead of 2. There are 27 specimens that do not have station information because of this.
meio_samples<-read_excel(path="/Users/eric/google_drive/MarineGEO/Meiofauna/Hawaii2017_meiofauna_MarineGEO.xlsx", sheet = "specimen data",skip=1)
#remove columns that don't appear in MarineGEO schema
meio_samples<-meio_samples[,-grep(pattern = "^X",x = names(meio_samples),perl=T)]
#add occurrence IDs to one investigators samples - this has been taken care of now
#meio_samples$occurrenceID[which(is.na(meio_samples$occurrenceID))]<-"UJ" 
#make occurrence IDs unique
#meio_samples$occurrenceID<-make.unique(meio_samples$occurrenceID, sep="_")

Format samples to schema

#change all empty columns from logical to character class
meio_samples[sapply(meio_samples, is.logical)] <- lapply(meio_samples[sapply(meio_samples, is.logical)],  as.character)
meio_samples$basisofRecord<-"specimen" #check with Frey that this is correct
meio_samples$institutionID<-"USNM"
# class(meio_samples$scientificName) #eventually parse this into taxon categories?
# class(meio_samples$taxonRank) #using this
# class(meio_samples$occurrenceID)
# class(meio_samples$catalogNumber)
# class(meio_samples$otherCatalogNumbers)
# class(meio_samples$organismScope)
# class(meio_samples$eventID)
# class(meio_samples$identifiedBy)
# class(meio_samples$individualCount)

Join the event data onto the occurrence data

meio<-left_join(meio_samples,meio_events,by="eventID")

Make A Map

#by individual
meio2<-meio %>% group_by(decimalLatitude, decimalLongitude) %>% summarize(individualCount=sum(individualCount,na.rm = T)) 
#by species
meio3 <- meio %>% group_by(scientificName, decimalLatitude, decimalLongitude) %>% summarize(count=n())
#richness
meio4<-meio3 %>% group_by(decimalLatitude,decimalLongitude) %>% summarize(richness=n())
meio5<-left_join(meio2,meio4)
meio_map<-ggmap(dmap) + geom_point(data = meio5, mapping = aes(x = decimalLongitude, y = decimalLatitude, size=individualCount, color=richness)) + scale_color_gradient(low = "green", high="red") + guides(color=guide_colorbar(title="Type Richness",), size=guide_legend(title="Individual Count")) + theme(axis.title=element_blank()) 
meio_map
ggsave(meio_map,filename="./output/meio_map.pdf")

ARMS

Import

arms_samples<-read_excel(path="/Users/eric/google_drive/MarineGEO/ARMS/MarineGEOHI_bioassessment_master-ARMS.xlsx", sheet = "Sample")

Format samples to schema

#change all empty columns from logical to character class
arms_samples[sapply(arms_samples, is.logical)] <- lapply(arms_samples[sapply(arms_samples, is.logical)],  as.character)
# class(arms_samples$occurrenceID)
# class(arms_samples$basisofRecord)
# class(arms_samples$catalogNumber)
# class(arms_samples$otherCatalogNumbers)
# class(arms_samples$organismScope) #were there some slurries too?
# class(arms_samples$eventID)
# class(arms_samples$scientificName) #eventually parse this into taxon categories?
# class(arms_samples$taxonRank) #using this
# class(arms_samples$identifiedBy)
# class(arms_samples$individualCount)
# change NAs for individualCount to 1 for now
arms_samples$individualCount[which(is.na(arms_samples$individualCount))]<-1
arms_samples$institutionID<-"USNM"

Join the event data onto the occurrence data

arms<-left_join(arms_samples,arms_events,by="eventID")

Make A Map

#by individual
arms2<-arms %>% group_by(decimalLatitude, decimalLongitude) %>% summarize(individualCount=sum(individualCount,na.rm = T)) 
#by species
arms3 <- arms %>% group_by(scientificName, decimalLatitude, decimalLongitude) %>% summarize(count=n())
#richness
arms4<-arms3 %>% group_by(decimalLatitude,decimalLongitude) %>% summarize(richness=n())
arms5<-left_join(arms2,arms4)
arms_map<-ggmap(dmap) + geom_point(data = arms5, mapping = aes(x = decimalLongitude, y = decimalLatitude, size=individualCount, color=richness)) + scale_color_gradient(low = "green", high="red") + guides(color=guide_colorbar(title="Type Richness",), size=guide_legend(title="Individual Count")) + theme(axis.title=element_blank()) 
arms_map
ggsave(arms_map,filename="./output/arms_map.pdf")

Visual Transects

Import

trans_samples<-read_excel(path="/Users/eric/google_drive/MarineGEO/Transects/bioassessment_KANV.xlsx", sheet = "Sample")
trans_organism_photos<-read_excel(path="/Users/eric/google_drive/MarineGEO/Transects/KANV_photo-vouchers_20170712.xlsx", sheet = "Sheet1")

Format, collapse and merge the media fields

Organism photos

# organism photos
## delete the field to be added later
trans_samples$associatedMedia<-NULL
#pop off the eventID again into its own field
trans_organism_photos$eventID<-sub(pattern="(KANV\\d\\d\\d)_.+",replacement = "\\1", trans_organism_photos$associatedMedia, perl=T)
#pop off the species name into its own field
trans_organism_photos$scientificName<-sub(pattern=".+_(\\d{8})_(\\w+-[a-z]+)_.+", replacement = "\\2", trans_organism_photos$associatedMedia,perl=T)
trans_organism_photos$scientificName<-sub(pattern="-", replacement=" ",x = trans_organism_photos$scientificName)
#pop off the initials of the collector, and replace with full name
trans_organism_photos$identifiedBy<-str_extract(pattern="ZF|RW", string=trans_organism_photos$associatedMedia)
trans_organism_photos$identifiedBy[which(trans_organism_photos$identifiedBy=="ZF")]<-"Zach Foltz"
trans_organism_photos$identifiedBy[which(trans_organism_photos$identifiedBy=="RW")]<-"Ross Whippo"
#use ddply to lump all associatedMedia into a single field, separated by a |
trans_associatedMedia<-ddply(trans_organism_photos, c("eventID","scientificName","identifiedBy"), transform, associatedMedia = paste(associatedMedia, collapse = "|"))
#remove all but the first instance
trans_associatedMedia<-trans_associatedMedia[!duplicated(trans_associatedMedia$associatedMedia),]
trans_samples<-left_join(trans_samples, trans_associatedMedia, by=c("eventID","scientificName","identifiedBy"))

Format samples to schema

#change all empty columns from logical to character class
trans_samples[sapply(trans_samples, is.logical)] <- lapply(trans_samples[sapply(trans_samples, is.logical)],  as.character)
# class(trans_samples$occurrenceID)
# class(trans_samples$basisofRecord)
# class(trans_samples$catalogNumber)
# class(trans_samples$otherCatalogNumbers)
# class(trans_samples$organismScope)
# class(trans_samples$eventID)
# class(trans_samples$scientificName) #eventually parse this into taxon categories?
# class(trans_samples$taxonRank) #using this
# class(trans_samples$identifiedBy)
# class(trans_samples$individualCount)
trans_samples$institutionID<-"USNM"

Join the event data onto the occurrence data

trans<-left_join(trans_samples,trans_events,by="eventID")

Make A Map

#by individual
trans2<-trans %>% group_by(decimalLatitude, decimalLongitude) %>% summarize(individualCount=sum(individualCount,na.rm = T)) 
#by species
trans3 <- trans %>% group_by(scientificName, decimalLatitude, decimalLongitude) %>% summarize(count=n(), individualCount=sum(individualCount,na.rm=T))
#richness
trans4<-trans3 %>% group_by(decimalLatitude,decimalLongitude) %>% summarize(richness=n())
trans5<-left_join(trans2,trans4)
trans_map<-ggmap(dmap) + geom_point(data = trans5, mapping = aes(x = decimalLongitude, y = decimalLatitude, size=individualCount, color=richness)) + scale_color_gradient(low = "green", high="red") + guides(color=guide_colorbar(title="Species Richness",), size=guide_legend(title="Individual Count")) + theme(axis.title=element_blank()) 
trans_map
ggsave(trans_map,filename="./output/trans_map.pdf")

Final Database

Now to join everything into one monster database

WriteXLS(c(MarineGEOHI2,as.data.frame(events)),ExcelFileName = "./output/MarineGEOHI_data_1.1.xlsx",SheetNames=c("Events","Samples"))
Error in WriteXLS(c(MarineGEOHI2, as.data.frame(events)), ExcelFileName = "./output/MarineGEOHI_data_1.1.xlsx",  : 
  One or more of the objects named in 'x' is not a data frame or does not exist
LS0tCnRpdGxlOiAiTWFyaW5lR0VPIERhdGEgRm9ybWF0dGluZywgU3VtbWFyaXppbmcgYW5kIGpvaW5pbmciCmF1dGhvcjogIkVyaWMgRC4gQ3JhbmRhbGwiCmRhdGU6ICI1LzI5LzIwMTciCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogeWVzCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldCgKCWVjaG8gPSBUUlVFLAoJbWVzc2FnZSA9IEZBTFNFLAoJd2FybmluZyA9IEZBTFNFCikKbGlicmFyeShwbHlyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdnbWFwKQpsaWJyYXJ5KHJlYWR4bCkKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkoc3RyaW5ncikKZmlsZWRpcjwtIn4vZ29vZ2xlX2RyaXZlL01hcmluZUdFTyIKCmJib3g8LWMobGVmdD0tMTU3Ljg1LGJvdHRvbT0gMjEuMzgscmlnaHQ9LTE1Ny43NSwgdG9wPTIxLjU1KQpkbWFwIDwtIGdldF9tYXAobG9jYXRpb24gPSBiYm94LCBtYXB0eXBlID0gInNhdGVsbGl0ZSIsIHNvdXJjZSA9ICJnb29nbGUiKQoKIyB0byBkbzoKCiMgc3BsaXQgc2NpZW50aWZpYyBuYW1lIGludG8gZ2VudXMgYW5kIHNwZWNpZXMgd2hlcmUgYXBwcm9wcmlhdGUKIyBzcC4gY2hhbmdlcyBsb3dlc3Qga25vd24gdG8gZ2VudXMKIyBvcmdhbmlzbVJlbWFya3MgPT0gIkJpc2hvcCIgLSBjaGFuZ2UgaW5zdGl0dXRpb25JRCB0byAiQmlzaG9wIE11c2V1bSIKIyBvcmdhbmlzbVNjb3BlID0gYnVsayBsb3QgaWYgaW5kaXZpZHVhbENvdW50ID4gMQojIGFkZCBvbiBsb2NhdGlvbiBpbmZvIHNwZWNpZmljIHRvIEthbmVvaGUgQmF5CgpgYGAKIyBCdWlsZCBFdmVudHMgRGF0YWJhc2UKCiMjIEZpc2gKYGBge3IgRmlzaCBFdmVudHN9CgpmaXNoX2V2ZW50czwtcmVhZF9leGNlbChwYXRoPSIvVXNlcnMvZXJpYy9nb29nbGVfZHJpdmUvTWFyaW5lR0VPL0Zpc2gvRklTSF9EQVRBXzIxSnVsMjAxNy54bHN4IixzaGVldD0iRXZlbnRzIikKCiMjIyBGb3JtYXQgZXZlbnRzIHRvIHNjaGVtYQoKI2NoYW5nZSBhbGwgZW1wdHkgY29sdW1ucyBmcm9tIGxvZ2ljYWwgdG8gY2hhcmFjdGVyIGNsYXNzCmZpc2hfZXZlbnRzW3NhcHBseShmaXNoX2V2ZW50cywgaXMubG9naWNhbCldIDwtIGxhcHBseShmaXNoX2V2ZW50c1tzYXBwbHkoZmlzaF9ldmVudHMsIGlzLmxvZ2ljYWwpXSwgIGFzLmNoYXJhY3RlcikKCiNjaGFuZ2UgZXZlbnRJRCB0byBqdXN0IHRoZSBLQU5GIHZhbHVlCmZpc2hfZXZlbnRzJGV2ZW50SUQ8LXN0cl9leHRyYWN0KGZpc2hfZXZlbnRzJGV2ZW50SUQsIktBTkZcXGRcXGRcXGQiKQoKI3JvdW5kIHRoZSBsYXQvbG9uZ3MgdG8gZm91ciBkaWdpdHMgKH4gMTBtIHVuY2VydGFpbnR5KQpmaXNoX2V2ZW50cyRkZWNpbWFsTGF0aXR1ZGU8LXJvdW5kKGFzLm51bWVyaWMoZmlzaF9ldmVudHMkZGVjaW1hbExhdGl0dWRlKSxkaWdpdHMgPSA0KQpmaXNoX2V2ZW50cyRkZWNpbWFsTG9uZ2l0dWRlPC1yb3VuZChhcy5udW1lcmljKGZpc2hfZXZlbnRzJGRlY2ltYWxMb25naXR1ZGUpLGRpZ2l0cyA9IDQpCgpmaXNoX2V2ZW50cyRjb29yZGluYXRlVW5jZXJ0YWludHlJbk1ldGVyczwtYXMubnVtZXJpYyhmaXNoX2V2ZW50cyRjb29yZGluYXRlVW5jZXJ0YWludHlJbk1ldGVycykgCgojIGNsYXNzKGZpc2hfZXZlbnRzJGdlb1JlZmVyZW5jZVByb3RvY29sKQojIGNsYXNzKGZpc2hfZXZlbnRzJG1heGltdW1EZXB0aEluTWV0ZXJzKQojIGNsYXNzKGZpc2hfZXZlbnRzJG1pbmltdW1EZXB0aEluTWV0ZXJzKQojIGNsYXNzKGZpc2hfZXZlbnRzJHJlY29yZGVkQnkpIAojIGNsYXNzKGZpc2hfZXZlbnRzJHNhbXBsaW5nUHJvdG9jb2wpICNzb21lIG1pc3NpbmcuIGFzayBEaWFuZSB0byBmaWxsIHRoaXMgaW4KIyBjbGFzcyhmaXNoX2V2ZW50cyRoYWJpdGF0QmlvdGljKQoKI3JlbW92ZSBjYXJyaWFnZSByZXR1cm5zIGZyb20gR2VvbW9ycGhvbG9naWNhbCBab25lCmZpc2hfZXZlbnRzJGhhYml0YXRHZW9tb3JwaG9sb2dpY2FsWm9uZTwtc3RyX3JlcGxhY2VfYWxsKGZpc2hfZXZlbnRzJGhhYml0YXRHZW9tb3JwaG9sb2dpY2FsWm9uZSxwYXR0ZXJuPSJcclxuIixyZXBsYWNlbWVudCA9ICIiKQpmaXNoX2V2ZW50cyRoYWJpdGF0U3Vic3RyYXRlPC1zdHJfcmVwbGFjZV9hbGwoZmlzaF9ldmVudHMkaGFiaXRhdFN1YnN0cmF0ZSxwYXR0ZXJuPSJcclxuIixyZXBsYWNlbWVudCA9ICIiKQoKZmlzaF9ldmVudHMkeWVhcjwtYXMubnVtZXJpYyhmaXNoX2V2ZW50cyR5ZWFyKQpmaXNoX2V2ZW50cyRtb250aDwtbWF0Y2goZmlzaF9ldmVudHMkbW9udGgsbW9udGguYWJiKQpmaXNoX2V2ZW50cyRkYXk8LWFzLm51bWVyaWMoZmlzaF9ldmVudHMkZGF5KQoKI1JlY29tbWVuZGVkIGZpZWxkcwojIGNsYXNzKGZpc2hfZXZlbnRzJGV2ZW50UmVtYXJrcykKIyBjbGFzcyhmaXNoX2V2ZW50cyRsb2NhbGl0eSkKIyBjbGFzcyhmaXNoX2V2ZW50cyRldmVudFJlbWFya3MpCiMgY2xhc3MoZmlzaF9ldmVudHMkdmVyYmF0aW1Db29yZGluYXRlcykKIyBjbGFzcyhmaXNoX2V2ZW50cyRldmVudE1lZGlhKQoKI3JlbW92ZSBlbmRpbmcgdGltZXMgZnJvbSBldmVudFRpbWUgZmllbGQKZmlzaF9ldmVudHMkZXZlbnRUaW1lPC1zdHJfZXh0cmFjdChzdHJpbmc9ZmlzaF9ldmVudHMkZXZlbnRUaW1lLHBhdHRlcm49Il5cXGRcXGQ6XFxkXFxkIikKCmBgYAoKIyMgQWxnYWUKCmBgYHtyIEFsZ2FlIEV2ZW50c30KCmFsZ2FlX2V2ZW50czwtcmVhZF9leGNlbCgiL1VzZXJzL2VyaWMvZ29vZ2xlX2RyaXZlL01hcmluZUdFTy9hbGdhZS9NYXJpbmVHRU9ISV9iaW9hc3Nlc3NtZW50X21hc3Rlcl9LQU5BLnhsc3giLCBzaGVldD0iU3RhdGlvbiIpCgojIyMgRm9ybWF0IGV2ZW50cyB0byBzY2hlbWEKCiNjaGFuZ2UgYWxsIGVtcHR5IGNvbHVtbnMgZnJvbSBsb2dpY2FsIHRvIGNoYXJhY3RlciBjbGFzcwphbGdhZV9ldmVudHNbc2FwcGx5KGFsZ2FlX2V2ZW50cywgaXMubG9naWNhbCldIDwtIGxhcHBseShhbGdhZV9ldmVudHNbc2FwcGx5KGFsZ2FlX2V2ZW50cywgaXMubG9naWNhbCldLCAgYXMuY2hhcmFjdGVyKQoKCiNyb3VuZCB0byA0IGRlY2ltYWwgZGlnaXRzICh+MTBtIHVuY2VydGFpbnR5KSBhbmQgbWVha2Ugc3VyZSBsb25naXR1ZGUgaXMgbmVnYXRpdmUKCmFsZ2FlX2V2ZW50cyRkZWNpbWFsTGF0aXR1ZGU8LXJvdW5kKGFzLm51bWVyaWMoYWxnYWVfZXZlbnRzJGRlY2ltYWxMYXRpdHVkZSksZGlnaXRzID0gNCkKYWxnYWVfZXZlbnRzJGRlY2ltYWxMb25naXR1ZGU8LWFicyhyb3VuZChhcy5udW1lcmljKGFsZ2FlX2V2ZW50cyRkZWNpbWFsTG9uZ2l0dWRlKSxkaWdpdHMgPSA0KSkqLTEKCiMgY2xhc3MoYWxnYWVfZXZlbnRzJGV2ZW50SUQpCiMgY2xhc3MoYWxnYWVfZXZlbnRzJGdlb1JlZmVyZW5jZVByb3RvY29sKSAjZ29vZAojIGNsYXNzKGFsZ2FlX2V2ZW50cyRjb29yZGluYXRlVW5jZXJ0YWludHlJbk1ldGVycykgI2dvb2QKIyBjbGFzcyhhbGdhZV9ldmVudHMkbWF4aW11bURlcHRoSW5NZXRlcnMpICNzb21lIG1pc3NpbmcuIGFzayBNZWxpbmRhIHRvIGZpbGwgdGhpcyBpbgojIGNsYXNzKGFsZ2FlX2V2ZW50cyRtaW5pbXVtRGVwdGhJbk1ldGVycykjc29tZSBtaXNzaW5nLiBhc2sgTWVsaW5kYSB0byBmaWxsIHRoaXMgaW4KIyBjbGFzcyhhbGdhZV9ldmVudHMkcmVjb3JkZWRCeSkgI3NvbWUgbWlzc2luZy4gYXNrIE1lbGluZGEgdG8gZmlsbCB0aGlzIGluCiMgY2xhc3MoYWxnYWVfZXZlbnRzJHNhbXBsaW5nUHJvdG9jb2wpICNzb21lIG1pc3NpbmcuIGFzayBNZWxpbmRhIHRvIGZpbGwgdGhpcyBpbgojIGNsYXNzKGFsZ2FlX2V2ZW50cyRgaGFiaXRhdEJpb3RpY2ApCiMgY2xhc3MoYWxnYWVfZXZlbnRzJGBoYWJpdGF0R2VvbW9ycGhvbG9naWNhbFpvbmVgKQojIGNsYXNzKGFsZ2FlX2V2ZW50cyRgaGFiaXRhdFN1YnN0cmF0ZWApCgoKI1JlY29tbWVuZGVkIGZpZWxkcwojIGNsYXNzKGFsZ2FlX2V2ZW50cyRldmVudFJlbWFya3MpCiMgY2xhc3MoYWxnYWVfZXZlbnRzJGxvY2FsaXR5KQojIGNsYXNzKGFsZ2FlX2V2ZW50cyRldmVudFJlbWFya3MpCiMgY2xhc3MoYWxnYWVfZXZlbnRzJHZlcmJhdGltQ29vcmRpbmF0ZXMpCiMgY2xhc3MoYWxnYWVfZXZlbnRzJGV2ZW50TWVkaWEpCgojZm9ybWF0IHRpbWUgY29ycmVjdGx5CmFsZ2FlX2V2ZW50cyRldmVudFRpbWU8LWFzLmNoYXJhY3RlcihwYXJzZV9kYXRlX3RpbWUoYWxnYWVfZXZlbnRzJGV2ZW50VGltZSwgb3JkZXJzPSJ5bWRITVMiLCB0ej0iSFNUIiksZm9ybWF0PSIlSDolTSIpCgoKYGBgCgojIyBNYWNyb2ludmVydGVicmF0ZXMKCmBgYHtyIEludmVydCBFdmVudHN9CgppbnZlcnRfZXZlbnRzPC1yZWFkX2V4Y2VsKHBhdGg9Ii9Vc2Vycy9lcmljL2dvb2dsZV9kcml2ZS9NYXJpbmVHRU8vSW52ZXJ0cy9CS0FORV8wNjMwMTdfRklNUy54bHN4Iiwgc2hlZXQgPSAiU3RhdGlvbiIsIHNraXA9MikKCgoKIyMjIEZvcm1hdCBldmVudHMgdG8gc2NoZW1hCiMgTm90ZTogaW52ZXJ0IGV2ZW50IGRhdGEgbmVlZCBhIGxvdCBvZiBjbGVhbmluZywgaW5jbHVkaW5nIGltcG9ydGluZyBzdGF0aW9ucyBmcm9tIHRoZSBhbGdhZSBhbmQgbWVpb2ZhdW5hIHRlYW0sIGFuZCBtYWtpbmcgbmV3IHN0YXRpb25zIHdpdGggIkEiIG9yICJCIiBhcHBlbmRlZC4gQ3VycmVudGx5IDgzOSBzYW1wbGVzIGRvIG5vdCBoYXZlIHN0YXRpb24gaW5mb3JtYXRpb24gYmVjYXVzZSBvZiB0aGlzLgoKIyByZW1vdmUgZXZlbnQgZmllbGRzIHRoYXQgZG9uJ3QgYXBwZWFyIGluIHRoZSBzY2hlbWEKaW52ZXJ0X2V2ZW50czwtaW52ZXJ0X2V2ZW50c1ssLWdyZXAocGF0dGVybiA9ICJeWCIseCA9IG5hbWVzKGludmVydF9ldmVudHMpLHBlcmw9VCldCgojY2hhbmdlIGFsbCBlbXB0eSBjb2x1bW5zIGZyb20gbG9naWNhbCB0byBjaGFyYWN0ZXIgY2xhc3MKaW52ZXJ0X2V2ZW50c1tzYXBwbHkoaW52ZXJ0X2V2ZW50cywgaXMubG9naWNhbCldIDwtIGxhcHBseShpbnZlcnRfZXZlbnRzW3NhcHBseShpbnZlcnRfZXZlbnRzLCBpcy5sb2dpY2FsKV0sICBhcy5jaGFyYWN0ZXIpCgojcm91bmQgdG8gNCBkZWNpbWFsIGRpZ2l0cyAofjEwbSB1bmNlcnRhaW50eSkgYW5kIG1lYWtlIHN1cmUgbG9uZ2l0dWRlIGlzIG5lZ2F0aXZlCmludmVydF9ldmVudHMkZGVjaW1hbExhdGl0dWRlPC1yb3VuZChhcy5udW1lcmljKGludmVydF9ldmVudHMkZGVjaW1hbExhdGl0dWRlKSxkaWdpdHMgPSA0KQppbnZlcnRfZXZlbnRzJGRlY2ltYWxMb25naXR1ZGU8LWFicyhyb3VuZChhcy5udW1lcmljKGludmVydF9ldmVudHMkZGVjaW1hbExvbmdpdHVkZSksZGlnaXRzID0gNCkpKi0xCgppbnZlcnRfZXZlbnRzJGdlb1JlZmVyZW5jZVByb3RvY29sPC0iR1BTIgppbnZlcnRfZXZlbnRzJGNvb3JkaW5hdGVVbmNlcnRhaW50eUluTWV0ZXJzPC0xMDAKCiMgY2xhc3MoaW52ZXJ0X2V2ZW50cyRtYXhpbXVtRGVwdGhJbk1ldGVycykgI3NvbWUgbWlzc2luZy4gYXNrIEpvaG4gdG8gZmlsbCB0aGlzIGluCiMgY2xhc3MoaW52ZXJ0X2V2ZW50cyRtaW5pbXVtRGVwdGhJbk1ldGVycykjc29tZSBtaXNzaW5nLiBhc2sgSm9obiB0byBmaWxsIHRoaXMgaW4KCiNGb3JtYXQgdGhlIGRhdGUgcHJvcGVybHksIGdldCByaWQgb2YgdGhlICJyYXciIGZpZWxkCmludmVydF9ldmVudHMkZGF5PC1kYXkoaW52ZXJ0X2V2ZW50cyRldmVudERhdGUpCmludmVydF9ldmVudHMkbW9udGg8LW1vbnRoKGludmVydF9ldmVudHMkZXZlbnREYXRlKQppbnZlcnRfZXZlbnRzJHllYXI8LXllYXIoaW52ZXJ0X2V2ZW50cyRldmVudERhdGUpCmludmVydF9ldmVudHMkZXZlbnREYXRlPC1OVUxMCgojIGNsYXNzKGludmVydF9ldmVudHMkcmVjb3JkZWRCeSkgI2dvb2QKIyBjbGFzcyhpbnZlcnRfZXZlbnRzJHNhbXBsaW5nUHJvdG9jb2wpICNzb21lIG1pc3NpbmcuIGFzayBKb2huIHRvIGZpbGwgdGhpcyBpbgojIGNsYXNzKGludmVydF9ldmVudHMkaGFiaXRhdEdlb21vcnBob2xvZ2ljYWxab25lKSAjc29tZSBtaXNzaW5nLiBhc2sgSm9obiB0byBmaWxsIHRoaXMgaW4uICN0aGlzIG5lZWRzIHRvIGJlIGFsaWduZWQgd2l0aCB0aGUgc2NoZW1hCiMgY2xhc3MoaW52ZXJ0X2V2ZW50cyRoYWJpdGF0U3Vic3RyYXRlKSAjIHNvbWUgbWlzc2luZy4gYXNrIEpvaG4gdG8gZmlsbCB0aGlzIGluLiAjdGhpcyBuZWVkcyB0byBiZSBhbGlnbmVkIHdpdGggdGhlIHNjaGVtYQoKCiNSZWNvbW1lbmRlZCBmaWVsZHMKIyBjbGFzcyhpbnZlcnRfZXZlbnRzJGxvY2FsaXR5KQojIGNsYXNzKGludmVydF9ldmVudHMkZXZlbnRSZW1hcmtzKQoKYGBgCgojIyBNZWlvZmF1bmEKCmBgYHtyIE1laW8gRXZlbnRzfQoKbWVpb19ldmVudHM8LXJlYWRfZXhjZWwocGF0aD0iL1VzZXJzL2VyaWMvZ29vZ2xlX2RyaXZlL01hcmluZUdFTy9NZWlvZmF1bmEvSGF3YWlpMjAxN19tZWlvZmF1bmFfTWFyaW5lR0VPLnhsc3giLCBzaGVldCA9ICJzdGF0aW9uIGRhdGEiLCBza2lwPTEpCgojcmVtb3ZlIGNvbHVtbnMgdGhhdCBkb24ndCBhcHBlYXIgaW4gTWFyaW5lR0VPIHNjaGVtYQptZWlvX2V2ZW50czwtbWVpb19ldmVudHNbLC1ncmVwKHBhdHRlcm4gPSAiXlgiLHggPSBuYW1lcyhtZWlvX2V2ZW50cykscGVybD1UKV0KCiMjIyBGb3JtYXQgZXZlbnRzIHRvIHNjaGVtYQoKI01pc3Npbmcgc3RhdGlvbiBLQU5NMDg3ISEhCgojY2hhbmdlIGFsbCBlbXB0eSBjb2x1bW5zIGZyb20gbG9naWNhbCB0byBjaGFyYWN0ZXIgY2xhc3MKbWVpb19ldmVudHNbc2FwcGx5KG1laW9fZXZlbnRzLCBpcy5sb2dpY2FsKV0gPC0gbGFwcGx5KG1laW9fZXZlbnRzW3NhcHBseShtZWlvX2V2ZW50cywgaXMubG9naWNhbCldLCAgYXMuY2hhcmFjdGVyKQoKI3JvdW5kIHRvIDQgZGVjaW1hbCBkaWdpdHMgKH4xMG0gdW5jZXJ0YWludHkpIGFuZCBtZWFrZSBzdXJlIGxvbmdpdHVkZSBpcyBuZWdhdGl2ZQptZWlvX2V2ZW50cyRkZWNpbWFsTGF0aXR1ZGU8LXJvdW5kKGFzLm51bWVyaWMobWVpb19ldmVudHMkZGVjaW1hbExhdGl0dWRlKSxkaWdpdHMgPSA0KQptZWlvX2V2ZW50cyRkZWNpbWFsTG9uZ2l0dWRlPC1hYnMocm91bmQoYXMubnVtZXJpYyhtZWlvX2V2ZW50cyRkZWNpbWFsTG9uZ2l0dWRlKSxkaWdpdHMgPSA0KSkqLTEKCm1laW9fZXZlbnRzJGNvb3JkaW5hdGVVbmNlcnRhaW50eUluTWV0ZXJzPC0xMDAKbWVpb19ldmVudHMkbWluaW11bURlcHRoSW5NZXRlcnM8LWFzLm51bWVyaWMobWVpb19ldmVudHMkbWluaW11bURlcHRoSW5NZXRlcnMpCm1laW9fZXZlbnRzJG1heGltdW1EZXB0aEluTWV0ZXJzPC1hcy5udW1lcmljKG1laW9fZXZlbnRzJG1heGltdW1EZXB0aEluTWV0ZXJzKQoKIyBjbGFzcyhtZWlvX2V2ZW50cyRtYXhpbXVtRGVwdGhJbk1ldGVycykKIyBjbGFzcyhtZWlvX2V2ZW50cyRtaW5pbXVtRGVwdGhJbk1ldGVycykKIyBjbGFzcyhtZWlvX2V2ZW50cyRyZWNvcmRlZEJ5KSAjYXNrIEZyZXlhIHRvIGZvbGxvdyBmb3JtYXQgLSBhZGQgbGFzdCBuYW1lcywgYW5kIHBpcGVzIGJldHdlZW4gbmFtZXMKIyBjbGFzcyhtZWlvX2V2ZW50cyRzYW1wbGluZ1Byb3RvY29sKSAjc29tZSBtaXNzaW5nLiBhc2sgRnJleWEgdG8gZmlsbCB0aGlzIGluCiMgY2xhc3MobWVpb19ldmVudHMkaGFiaXRhdEdlb21vcnBob2xvZ2ljYWxab25lKSAjc29tZSBtaXNzaW5nLiBhc2sgRnJleWEgdG8gZmlsbCB0aGlzIGluCiMgY2xhc3MobWVpb19ldmVudHMkaGFiaXRhdFN1YnN0cmF0ZSkgIyBzb21lIG1pc3NpbmcuIGFzayBGcmV5YSB0byBmaWxsIHRoaXMgaW4KIyBjbGFzcyhtZWlvX2V2ZW50cyRoYWJpdGF0QmlvdGljKQoKI1JlY29tbWVuZGVkIGZpZWxkcwojIGNsYXNzKG1laW9fZXZlbnRzJGxvY2FsaXR5KQojIGNsYXNzKG1laW9fZXZlbnRzJGV2ZW50UmVtYXJrcykKCm1laW9fZXZlbnRzJGRheTwtZGF5KG1laW9fZXZlbnRzJGV2ZW50RGF0ZSkKbWVpb19ldmVudHMkbW9udGg8LW1vbnRoKG1laW9fZXZlbnRzJGV2ZW50RGF0ZSkKbWVpb19ldmVudHMkeWVhcjwteWVhcihtZWlvX2V2ZW50cyRldmVudERhdGUpCm1laW9fZXZlbnRzJGV2ZW50RGF0ZTwtTlVMTAoKI2Zvcm1hdCB0aGUgJF4jJiogdGltZSBjb3JyZWN0bHkKbWVpb19ldmVudHMkZXZlbnRUaW1lPC1mb3JtYXQoLlBPU0lYY3QoODY0MDAqYXMubnVtZXJpYyhtZWlvX2V2ZW50cyRldmVudFRpbWUpLCAiVVRDIiksICIlSDolTSIpCiNtZWlvX2V2ZW50cyRldmVudFRpbWU8LWFzLmNoYXJhY3RlcihwYXJzZV9kYXRlX3RpbWUobWVpb19ldmVudHMkZXZlbnRUaW1lLCBvcmRlcnM9InltZEhNUyIsIHR6PSJIU1QiKSxmb3JtYXQ9IiVIOiVNIikKCm1laW9fZXZlbnRzJGV2ZW50TWVkaWE8LSJOIgoKYGBgCgojIyBBUk1TCgpgYGB7ciBBUk1TIGV2ZW50c30KYXJtc19ldmVudHM8LXJlYWRfZXhjZWwocGF0aD0iL1VzZXJzL2VyaWMvZ29vZ2xlX2RyaXZlL01hcmluZUdFTy9BUk1TL01hcmluZUdFT0hJX2Jpb2Fzc2Vzc21lbnRfbWFzdGVyLUFSTVMueGxzeCIsIHNoZWV0ID0gIlN0YXRpb24iKQoKIyMjIEZvcm1hdCBldmVudHMgdG8gc2NoZW1hCgojY2hhbmdlIGFsbCBlbXB0eSBjb2x1bW5zIGZyb20gbG9naWNhbCB0byBjaGFyYWN0ZXIgY2xhc3MKYXJtc19ldmVudHNbc2FwcGx5KGFybXNfZXZlbnRzLCBpcy5sb2dpY2FsKV0gPC0gbGFwcGx5KGFybXNfZXZlbnRzW3NhcHBseShhcm1zX2V2ZW50cywgaXMubG9naWNhbCldLCAgYXMuY2hhcmFjdGVyKQoKCiNyb3VuZCB0byA0IGRlY2ltYWwgZGlnaXRzICh+MTBtIHVuY2VydGFpbnR5KSBhbmQgbWVha2Ugc3VyZSBsb25naXR1ZGUgaXMgbmVnYXRpdmUKYXJtc19ldmVudHMkZGVjaW1hbExhdGl0dWRlPC1yb3VuZChhcy5udW1lcmljKGFybXNfZXZlbnRzJGRlY2ltYWxMYXRpdHVkZSksZGlnaXRzID0gNCkKYXJtc19ldmVudHMkZGVjaW1hbExvbmdpdHVkZTwtYWJzKHJvdW5kKGFzLm51bWVyaWMoYXJtc19ldmVudHMkZGVjaW1hbExvbmdpdHVkZSksZGlnaXRzID0gNCkpKi0xCmFybXNfZXZlbnRzJGNvb3JkaW5hdGVVbmNlcnRhaW50eUluTWV0ZXJzPC0xMAoKYXJtc19ldmVudHMkbWluaW11bURlcHRoSW5NZXRlcnM8LWFzLm51bWVyaWMoYXJtc19ldmVudHMkbWluaW11bURlcHRoSW5NZXRlcnMpCgojIGNsYXNzKGFybXNfZXZlbnRzJGdlb1JlZmVyZW5jZVByb3RvY29sKQojIGNsYXNzKGFybXNfZXZlbnRzJGV2ZW50SUQpCiMgY2xhc3MoYXJtc19ldmVudHMkbWF4aW11bURlcHRoSW5NZXRlcnMpCiMgY2xhc3MoYXJtc19ldmVudHMkcmVjb3JkZWRCeSkgI2FzayBMYWV0aXRpYSB0byBmb2xsb3cgbmFtZSBmb3JtYXQKIyBjbGFzcyhhcm1zX2V2ZW50cyRzYW1wbGluZ1Byb3RvY29sKQojIGNsYXNzKGFybXNfZXZlbnRzJGhhYml0YXRHZW9tb3JwaG9sb2dpY2FsWm9uZSkKIyBjbGFzcyhhcm1zX2V2ZW50cyRoYWJpdGF0U3Vic3RyYXRlKSAKIyBjbGFzcyhhcm1zX2V2ZW50cyRoYWJpdGF0QmlvdGljKQoKI1JlY29tbWVuZGVkIGZpZWxkcwojIGNsYXNzKGFybXNfZXZlbnRzJGxvY2FsaXR5KQojIGNsYXNzKGFybXNfZXZlbnRzJHllYXIpCiMgY2xhc3MoYXJtc19ldmVudHMkbW9udGgpCiMgY2xhc3MoYXJtc19ldmVudHMkZGF5KQoKYXJtc19ldmVudHMkZXZlbnRNZWRpYTwtIlkiICNzdGlsbCBuZWVkIHRvIGdldCB0aGVzZSBmcm9tIExhZXRpdGlhCgpgYGAKCiMjIFZpc3VhbCBUcmFuc2VjdHMKCmBgYHtyIFRyYW5zZWN0IEV2ZW50c30KdHJhbnNfZXZlbnRzPC1yZWFkX2V4Y2VsKHBhdGg9Ii9Vc2Vycy9lcmljL2dvb2dsZV9kcml2ZS9NYXJpbmVHRU8vVHJhbnNlY3RzL2Jpb2Fzc2Vzc21lbnRfS0FOVi54bHN4Iiwgc2hlZXQgPSAiU3RhdGlvbiIpCgp0cmFuc19ldmVudF9waG90b3M8LXJlYWRfZXhjZWwocGF0aD0iL1VzZXJzL2VyaWMvZ29vZ2xlX2RyaXZlL01hcmluZUdFTy9UcmFuc2VjdHMvS0FOVl9iZW50aGljLXBob3Rvc19maWxlbmFtZXNfMjAxNzA3MTEueGxzeCIsIHNoZWV0ID0gIlNoZWV0MSIpCgojIGV2ZW50IHBob3RvcwojcG9wIG9mZiB0aGUgZXZlbnRJRCBpbnRvIGl0cyBvd24gZmllbGQKdHJhbnNfZXZlbnRfcGhvdG9zJGV2ZW50SUQ8LXN1YihwYXR0ZXJuPSIoS0FOVlxcZFxcZFxcZClfLisiLHJlcGxhY2VtZW50ID0gIlxcMSIsIHRyYW5zX2V2ZW50X3Bob3RvcyRldmVudE1lZGlhLCBwZXJsPVQpCgojdXNlIGRkcGx5IHRvIGx1bXAgYWxsIGV2ZW50TWVkaWEgaW50byBhIHNpbmdsZSBmaWVsZCwgc2VwYXJhdGVkIGJ5IGEgfAp0cmFuc19ldmVudE1lZGlhPC1kZHBseSh0cmFuc19ldmVudF9waG90b3MsICJldmVudElEIiwgdHJhbnNmb3JtLCBldmVudE1lZGlhID0gcGFzdGUoZXZlbnRNZWRpYSwgY29sbGFwc2UgPSAifCIpKQoKI2tlZXAgb25seSB0aGUgZmlyc3QgaW5zdGFuY2Ugb2YgZWFjaCBvY2N1cnJlbmNlSUQKdHJhbnNfZXZlbnRNZWRpYTwtdHJhbnNfZXZlbnRNZWRpYVshZHVwbGljYXRlZCh0cmFuc19ldmVudE1lZGlhJGV2ZW50SUQpLF0KCiNkZWxldGUgb3JpZ2luYWwgZXZlbnRNZWRpYSBjb2x1bW4gYW5kIGpvaW4gb24gdGhlIG5ldyBvbmUKdHJhbnNfZXZlbnRzJGV2ZW50TWVkaWE8LU5VTEwKdHJhbnNfZXZlbnRzPC1sZWZ0X2pvaW4odHJhbnNfZXZlbnRzLCB0cmFuc19ldmVudE1lZGlhLCBieT0iZXZlbnRJRCIpCgoKIyMjIEZvcm1hdCBldmVudHMgdG8gc2NoZW1hCiNjaGFuZ2UgYWxsIGVtcHR5IGNvbHVtbnMgZnJvbSBsb2dpY2FsIHRvIGNoYXJhY3RlciBjbGFzcwp0cmFuc19ldmVudHNbc2FwcGx5KHRyYW5zX2V2ZW50cywgaXMubG9naWNhbCldIDwtIGxhcHBseSh0cmFuc19ldmVudHNbc2FwcGx5KHRyYW5zX2V2ZW50cywgaXMubG9naWNhbCldLCAgYXMuY2hhcmFjdGVyKQojcm91bmQgdG8gNCBkZWNpbWFsIGRpZ2l0cyAofjEwbSB1bmNlcnRhaW50eSkgYW5kIG1lYWtlIHN1cmUgbG9uZ2l0dWRlIGlzIG5lZ2F0aXZlCnRyYW5zX2V2ZW50cyRkZWNpbWFsTGF0aXR1ZGU8LXJvdW5kKGFzLm51bWVyaWModHJhbnNfZXZlbnRzJGRlY2ltYWxMYXRpdHVkZSksZGlnaXRzID0gNCkKdHJhbnNfZXZlbnRzJGRlY2ltYWxMb25naXR1ZGU8LWFicyhyb3VuZChhcy5udW1lcmljKHRyYW5zX2V2ZW50cyRkZWNpbWFsTG9uZ2l0dWRlKSxkaWdpdHMgPSA0KSkqLTEKCnRyYW5zX2V2ZW50cyRtaW5pbXVtRGVwdGhJbk1ldGVyczwtYXMubnVtZXJpYyh0cmFuc19ldmVudHMkbWluaW11bURlcHRoSW5NZXRlcnMpCgojIGNsYXNzKHRyYW5zX2V2ZW50cyRldmVudElEKQojIGNsYXNzKHRyYW5zX2V2ZW50cyRjb29yZGluYXRlVW5jZXJ0YWludHlJbk1ldGVycykKIyBjbGFzcyh0cmFuc19ldmVudHMkbWF4aW11bURlcHRoSW5NZXRlcnMpCiMgY2xhc3ModHJhbnNfZXZlbnRzJHJlY29yZGVkQnkpIAojIGNsYXNzKHRyYW5zX2V2ZW50cyRzYW1wbGluZ1Byb3RvY29sKQojIGNsYXNzKHRyYW5zX2V2ZW50cyRoYWJpdGF0R2VvbW9ycGhvbG9naWNhbFpvbmUpCiMgY2xhc3ModHJhbnNfZXZlbnRzJGhhYml0YXRTdWJzdHJhdGUpCiMgY2xhc3ModHJhbnNfZXZlbnRzJGhhYml0YXRCaW90aWMpCgojUmVjb21tZW5kZWQgZmllbGRzCiMgY2xhc3ModHJhbnNfZXZlbnRzJGxvY2FsaXR5KQojIGNsYXNzKHRyYW5zX2V2ZW50cyR5ZWFyKQojIGNsYXNzKHRyYW5zX2V2ZW50cyRtb250aCkKIyBjbGFzcyh0cmFuc19ldmVudHMkZGF5KQoKdHJhbnNfZXZlbnRzJGV2ZW50TWVkaWE8LSJZIgp0cmFuc19ldmVudHMkZXZlbnRUaW1lPC1hcy5jaGFyYWN0ZXIocGFyc2VfZGF0ZV90aW1lKHRyYW5zX2V2ZW50cyRldmVudFRpbWUsIG9yZGVycz0ieW1kSE1TIiwgdHo9IkhTVCIpLGZvcm1hdD0iJUg6JU0iKQoKYGBgCgojIyBKb2luIEV2ZW50cwoKYGBge3IgSm9pbiBFdmVudHN9CmV2ZW50czwtZnVsbF9qb2luKGZpc2hfZXZlbnRzLGFsZ2FlX2V2ZW50cykKZXZlbnRzPC1mdWxsX2pvaW4oZXZlbnRzLGludmVydF9ldmVudHMpCmV2ZW50czwtZnVsbF9qb2luKGV2ZW50cyxtZWlvX2V2ZW50cykKZXZlbnRzPC1mdWxsX2pvaW4oZXZlbnRzLGFybXNfZXZlbnRzKQpldmVudHM8LWZ1bGxfam9pbihldmVudHMsdHJhbnNfZXZlbnRzKQoKCgpgYGAKIyBCdWlsZCBzYW1wbGUgZGF0YWJhc2VzCgojIyBGaXNoCgojIyMgSW1wb3J0CmBgYHtyIEZpc2hfaW1wb3J0fQojIEZpcnN0IGdvIHRocm91Z2ggYW5kIG1ha2Ugc3VyZSBhbGwgc3RhdGlvbnMgaGF2ZSBMYXQvTG9uZ3MsIG9yIGFzIG1hbnkgYXMgcG9zc2libGUuIERlbGV0ZSBzZWNvbmRhcnkgbGF0L2xvbmdzCiNyZWFkIGluIHRoZSBzYW1wbGUgZGF0YSwgc2tpcHBpbmcgZmlyc3QgMyBsaW5lcyBvZiBvdGhlciBoZWFkZXJzLiBGb3JtYXQgYWxsIHRpbWVzIGFzIGhoOm1tIGluIEV4Y2VsLCBwYXN0ZSBpbnRvIHRleHR3cmFuZ2xlciBpZiB0aGV5IG5lZWQgaG9tb2dlbml6YXRpb24gKGkuZS4gbXVsdGlwbGUgZm9ybWF0cyBvZiB0aW1lcykKCmZpc2hfc2FtcGxlczwtcmVhZF9leGNlbChwYXRoPSIvVXNlcnMvZXJpYy9nb29nbGVfZHJpdmUvTWFyaW5lR0VPL0Zpc2gvRklTSF9EQVRBXzIxSnVsMjAxNy54bHN4IixzaGVldD0iU2FtcGxlcyIpCgpmaXNoX2dlbmV0aWM8LXJlYWRfZXhjZWwocGF0aD0iL1VzZXJzL2VyaWMvZ29vZ2xlX2RyaXZlL01hcmluZUdFTy9GaXNoL0ZJU0hfREFUQV8yMUp1bDIwMTcueGxzeCIsc2hlZXQ9IkdlbmV0aWMgc2FtcGxlcyIpCiN0aGVzZSBjb21tYW5kcyBhcHBseSB0byB0aGUgb3JpZ2luYWwgZmlzaC1ncm91cCB0ZW1wbGF0ZQojcmVtb3ZlIGNvbHVtbnMgd2l0aG91dCBtYXBwZWQgRHdDIHRlcm1zIG1hcHBlZAojZmlzaF9zYW1wbGVzPC1maXNoX3NhbXBsZXNbLC1ncmVwKHBhdHRlcm4gPSAiXlgiLHggPSBuYW1lcyhmaXNoX3NhbXBsZXMpLHBlcmw9VCldCiNmaXNoX2V2ZW50czwtZmlzaF9ldmVudHNbLC1ncmVwKHBhdHRlcm4gPSAiXlgiLHggPSBuYW1lcyhmaXNoX2V2ZW50cykscGVybD1UKV0KCiNyZW1vdmUgcmVjb3JkcyB3aXRob3V0IG9jY3VycmVuY2VJRHMgKHRlbXAgYmVmb3JlIGZpbmFsIGRhdGFzZXQpCiNmaXNoX3NhbXBsZXM8LWZpc2hfc2FtcGxlc1std2hpY2goaXMubmEoZmlzaF9zYW1wbGVzJG9jY3VycmVuY2VJRCkpLF0KI3RyYW5zbGF0ZSBmaWVsZElEcyB0byBldmVudElEcwojZmlzaF9zYW1wbGVzJGV2ZW50SUQ8LWdzdWIoIkxSUCAxNy0iLCJLQU5GMCIsZmlzaF9zYW1wbGVzJGV2ZW50SUQpCiN1c2UgZGRwbHkgdG8gbHVtcCBhbGwgbWF0ZXJpYWxTYW1wbGVJRHMgaW50byBhIHNpbmdsZSBmaWVsZCwgc2VwYXJhdGVkIGJ5IGEgfAojZmlzaF9zYW1wbGVzPC1kZHBseShmaXNoX3NhbXBsZXMsICJvY2N1cnJlbmNlSUQiLCB0cmFuc2Zvcm0sIG1hdGVyaWFsU2FtcGxlSUQgPSAjcGFzdGUobWF0ZXJpYWxTYW1wbGVJRCwgY29sbGFwc2UgPSAifCIpKQoja2VlcCBvbmx5IHRoZSBmaXJzdCBpbnN0YW5jZSBvZiBlYWNoIG9jY3VycmVuY2VJRAojZmlzaF9zYW1wbGVzPC1maXNoX3NhbXBsZXNbIWR1cGxpY2F0ZWQoZmlzaF9zYW1wbGVzJG9jY3VycmVuY2VJRCksXQpgYGAKCgojIyMgRm9ybWF0IHNhbXBsZXMgdG8gc2NoZW1hCgpgYGB7ciBmb3JtYXQgZmlzaCBzYW1wbGVzfQojY2hhbmdlIGFsbCBlbXB0eSBjb2x1bW5zIGZyb20gbG9naWNhbCB0byBjaGFyYWN0ZXIgY2xhc3MKZmlzaF9zYW1wbGVzW3NhcHBseShmaXNoX3NhbXBsZXMsIGlzLmxvZ2ljYWwpXSA8LSBsYXBwbHkoZmlzaF9zYW1wbGVzW3NhcHBseShmaXNoX3NhbXBsZXMsIGlzLmxvZ2ljYWwpXSwgIGFzLmNoYXJhY3RlcikKCiNGaXggdGhlIGV2ZW50SURzCmZpc2hfc2FtcGxlcyRldmVudElEPC1zdHJfZXh0cmFjdChmaXNoX3NhbXBsZXMkZXZlbnRJRCwiS0FORlxcZFxcZFxcZCIpCgoKZmlzaF9zYW1wbGVzJG90aGVyQ2F0YWxvZ051bWJlcnM8LU5VTEwgIyBkcm9wIHRoaXMgZm9yIG5vdyAtIGl0IHdpbGwgYmUgcmVwbGFjZWQgYnkgZmlzaF9iaW9yZXAgYmVsb3cKCiMgY2xhc3MoZmlzaF9zYW1wbGVzWyx3aGljaChzYXBwbHkoZmlzaF9zYW1wbGVzLCBpcy5sb2dpY2FsKSldKTwtImNoYXJhY3RlciIKIyBjbGFzcyhmaXNoX3NhbXBsZXMkb2NjdXJyZW5jZUlEKQojIGNsYXNzKGZpc2hfc2FtcGxlcyRiYXNpc29mUmVjb3JkKQojIGNsYXNzKGZpc2hfc2FtcGxlcyRjYXRhbG9nTnVtYmVyKTwtImNoYXJhY3RlciIKIyBjbGFzcyhmaXNoX3NhbXBsZXMkb3JnYW5pc21TY29wZSkKIyBjbGFzcyhmaXNoX3NhbXBsZXMkZXZlbnRJRCkKIyBjbGFzcyhmaXNoX3NhbXBsZXMkc2NpZW50aWZpY05hbWUpICNldmVudHVhbGx5IHBhcnNlIHRoaXMgaW50byB0YXhvbiBjYXRlZ29yaWVzPwojIGNsYXNzKGZpc2hfc2FtcGxlcyR0YXhvblJhbmspICN1c2luZyB0aGlzCiMgY2xhc3MoZmlzaF9zYW1wbGVzJGluZGl2aWR1YWxDb3VudCkKIyBjbGFzcyhmaXNoX3NhbXBsZXMkaW5zdGl0dXRpb25JRCkKCiMgbWFrZSBpZGVudGlmaWVkQnkgZ28gZmlyc3RuYW1lIGxhc3RuYW1lCmZpc2hfc2FtcGxlcyRpZGVudGlmaWVkQnk8LXN0cl9yZXBsYWNlKGZpc2hfc2FtcGxlcyRpZGVudGlmaWVkQnksIHBhdHRlcm49IihcXHcrKSwgKC4rKSIsIHJlcGxhY2VtZW50PSJcXDIgXFwxIikKCmZpc2hfc2FtcGxlcyRjYXRhbG9nTnVtYmVyPC1hcy5jaGFyYWN0ZXIoZmlzaF9zYW1wbGVzJGNhdGFsb2dOdW1iZXIpCgpgYGAKCiMjIyBGb3JtYXQgdGhlIGJpb3JlcG9zaXRvcnkgaW5mbwpgYGB7ciBmaXNoIGJpb3JlcG9zaXRvcnl9CmNvbG5hbWVzKGZpc2hfZ2VuZXRpYylbNV08LSJCaW9yZXBvc2l0b3J5SUQiCmNvbG5hbWVzKGZpc2hfZ2VuZXRpYylbNl08LSJ0aXNzdWVOb3RlcyIKY29sbmFtZXMoZmlzaF9nZW5ldGljKVsyXTwtIm9jY3VycmVuY2VJRCIKI3VzZSBkZHBseSB0byBsdW1wIGFsbCBtYXRlcmlhbFNhbXBsZUlEcyBpbnRvIGEgc2luZ2xlIGZpZWxkLCBzZXBhcmF0ZWQgYnkgYSB8CmZpc2hfYmlvcmVwPC1kZHBseShmaXNoX2dlbmV0aWMsICJvY2N1cnJlbmNlSUQiLCB0cmFuc2Zvcm0sIG90aGVyQ2F0YWxvZ051bWJlcnMgPSBwYXN0ZShCaW9yZXBvc2l0b3J5SUQsIGNvbGxhcHNlID0gInwiKSwgdGlzc3VlTm90ZXMgPSBwYXN0ZSh0aXNzdWVOb3RlcywgY29sbGFwc2U9InwiKSkKI2tlZXAgb25seSB0aGUgZmlyc3QgaW5zdGFuY2Ugb2YgZWFjaCBvY2N1cnJlbmNlSUQKZmlzaF9iaW9yZXA8LWZpc2hfYmlvcmVwWyFkdXBsaWNhdGVkKGZpc2hfYmlvcmVwJG90aGVyQ2F0YWxvZ051bWJlcnMpLF0KZmlzaF9iaW9yZXAkb3RoZXJDYXRhbG9nTnVtYmVyczwtYXMuY2hhcmFjdGVyKGZpc2hfYmlvcmVwJG90aGVyQ2F0YWxvZ051bWJlcnMpCmBgYAoKIyMjIEpvaW4gdGhlIGV2ZW50IGRhdGEgb250byB0aGUgb2NjdXJyZW5jZSBkYXRhCgpgYGB7ciBmaXNoIGpvaW59CgojZmlyc3Qgam9pbiB0aGUgYmlvcmVwIG51bWJlcnMgdG8gdGhpcyBkYXRhCmZpc2hfc2FtcGxlczwtbGVmdF9qb2luKGZpc2hfc2FtcGxlcyxmaXNoX2Jpb3JlcFssYygyLDYsNyldLGJ5PSJvY2N1cnJlbmNlSUQiKQojbm93IGpvaW4gc2FtcGxlcyBhbmQgZXZlbnRzCmZpc2g8LWxlZnRfam9pbihmaXNoX3NhbXBsZXMsZXZlbnRzLGJ5PSJldmVudElEIikKCgpgYGAKCiMjIyBNYWtlIGEgTWFwCgpgYGB7ciBmaXNoIG1hcHN9CiNvcHRpb25hbGx5IG1ha2UgaXQgZnJvbSB0aGUgcG9pbnRzIHByb3ZpZGVkCiNiYm94PC1tYWtlX2Jib3gobG9uPWZpc2gyJGRlY2ltYWxMb25naXR1ZGUsbGF0PWZpc2gyJGRlY2ltYWxMYXRpdHVkZSkKI2J5IGluZGl2aWR1YWwKZmlzaDI8LWZpc2ggJT4lIGdyb3VwX2J5KGRlY2ltYWxMYXRpdHVkZSwgZGVjaW1hbExvbmdpdHVkZSkgJT4lIHN1bW1hcml6ZShjb3VudD1uKCkpIAoKI2J5IHNwZWNpZXMKZmlzaDMgPC0gZmlzaCAlPiUgZ3JvdXBfYnkoc2NpZW50aWZpY05hbWUsIGRlY2ltYWxMYXRpdHVkZSwgZGVjaW1hbExvbmdpdHVkZSkgJT4lIHN1bW1hcml6ZShjb3VudD1uKCkpCgojcmljaG5lc3MKZmlzaDQ8LWZpc2gzICU+JSBncm91cF9ieShkZWNpbWFsTGF0aXR1ZGUsZGVjaW1hbExvbmdpdHVkZSkgJT4lIHN1bW1hcml6ZShyaWNobmVzcz1uKCkpCgpmaXNoNjwtbGVmdF9qb2luKGZpc2gyLGZpc2g0KQoKCmZpc2hfbWFwPC1nZ21hcChkbWFwKSArIGdlb21fcG9pbnQoZGF0YSA9IGZpc2g2LCBtYXBwaW5nID0gYWVzKHggPSBkZWNpbWFsTG9uZ2l0dWRlLCB5ID0gZGVjaW1hbExhdGl0dWRlLCBzaXplPWNvdW50LCBjb2xvcj1yaWNobmVzcykpICsgc2NhbGVfY29sb3JfZ3JhZGllbnQobG93ID0gImdyZWVuIiwgaGlnaD0icmVkIikgKyBndWlkZXMoY29sb3I9Z3VpZGVfY29sb3JiYXIodGl0bGU9IlNwZWNpZXMgUmljaG5lc3MiLCksIHNpemU9Z3VpZGVfbGVnZW5kKHRpdGxlPSJJbmRpdmlkdWFsIENvdW50IikpICsgdGhlbWUoYXhpcy50aXRsZT1lbGVtZW50X2JsYW5rKCkpCgpmaXNoX21hcAoKCmdnc2F2ZShmaXNoX21hcCxmaWxlbmFtZT0iLi9vdXRwdXQvZmlzaF9tYXAucGRmIikKCmBgYAoKCiMjIEFsZ2FlCgojIyMgSW1wb3J0CmBgYHtyIEFsZ2FlIGltcG9ydH0KI2VkaXQgZXZlbnRJRHMgZm9yIGNhcGl0YWxpemF0aW9uCgphbGdhZV9zYW1wbGVzPC1yZWFkX2V4Y2VsKCIvVXNlcnMvZXJpYy9nb29nbGVfZHJpdmUvTWFyaW5lR0VPL2FsZ2FlL01hcmluZUdFT0hJX2Jpb2Fzc2Vzc21lbnRfbWFzdGVyX0tBTkEueGxzeCIsIHNoZWV0PSJTYW1wbGUiKQoKYGBgCgojIyMgRm9ybWF0IHNhbXBsZXMgdG8gc2NoZW1hCgpgYGB7ciBmb3JtYXQgYWxnYWUgc2FtcGxlc30KI2NoYW5nZSBhbGwgZW1wdHkgY29sdW1ucyBmcm9tIGxvZ2ljYWwgdG8gY2hhcmFjdGVyIGNsYXNzCmFsZ2FlX3NhbXBsZXNbc2FwcGx5KGFsZ2FlX3NhbXBsZXMsIGlzLmxvZ2ljYWwpXSA8LSBsYXBwbHkoYWxnYWVfc2FtcGxlc1tzYXBwbHkoYWxnYWVfc2FtcGxlcywgaXMubG9naWNhbCldLCAgYXMuY2hhcmFjdGVyKQoKIyBjbGFzcyhhbGdhZV9zYW1wbGVzJG9jY3VycmVuY2VJRCkKIyBjbGFzcyhhbGdhZV9zYW1wbGVzJGNhdGFsb2dOdW1iZXIpCiMgY2xhc3MoYWxnYWVfc2FtcGxlcyRvdGhlckNhdGFsb2dOdW1iZXJzKQojIGNsYXNzKGFsZ2FlX3NhbXBsZXMkb3JnYW5pc21TY29wZSkKIyBjbGFzcyhhbGdhZV9zYW1wbGVzJGV2ZW50SUQpCiMgY2xhc3MoYWxnYWVfc2FtcGxlcyRzY2llbnRpZmljTmFtZSkgI2V2ZW50dWFsbHkgcGFyc2UgdGhpcyBpbnRvIHRheG9uIGNhdGVnb3JpZXM/CiMgY2xhc3MoYWxnYWVfc2FtcGxlcyR0YXhvblJhbmspICMgTWVsaW5kYSBuZWVkcyB0byBwb3B1bGF0ZSB0aGlzLi4uCiMgY2xhc3MoYWxnYWVfc2FtcGxlcyRpZGVudGlmaWVkQnkpCiMgY2xhc3MoYWxnYWVfc2FtcGxlcyRpbmRpdmlkdWFsQ291bnQpCgphbGdhZV9zYW1wbGVzJGJhc2lzb2ZSZWNvcmQ8LSJzcGVjaW1lbiIKYWxnYWVfc2FtcGxlcyRpbnN0aXR1dGlvbklEPC0iVVNOTSIKCgoKYGBgCgoKCgojIyMgSm9pbiB0aGUgZXZlbnQgZGF0YSBvbnRvIHRoZSBvY2N1cnJlbmNlIGRhdGEKCmBgYHtyIGpvaW4gYWxnYWV9CgphbGdhZTwtbGVmdF9qb2luKGFsZ2FlX3NhbXBsZXMsZXZlbnRzLGJ5PSJldmVudElEIikKCmBgYAoKIyMjIE1ha2UgQSBNYXAKYGBge3IgYWxnYWUgbWFwc30KCgojYnkgaW5kaXZpZHVhbAphbGdhZTI8LWFsZ2FlICU+JSBncm91cF9ieShkZWNpbWFsTGF0aXR1ZGUsIGRlY2ltYWxMb25naXR1ZGUpICU+JSBzdW1tYXJpemUoY291bnQ9bigpKSAKCiNieSBzcGVjaWVzCmFsZ2FlMyA8LSBhbGdhZVstd2hpY2goYWxnYWUkc2NpZW50aWZpY05hbWU9PSI/IiksXSAlPiUgZ3JvdXBfYnkoc2NpZW50aWZpY05hbWUsIGRlY2ltYWxMYXRpdHVkZSwgZGVjaW1hbExvbmdpdHVkZSkgJT4lIHN1bW1hcml6ZShjb3VudD1uKCkpCgojcmljaG5lc3MKYWxnYWU0PC1hbGdhZTMgJT4lIGdyb3VwX2J5KGRlY2ltYWxMYXRpdHVkZSxkZWNpbWFsTG9uZ2l0dWRlKSAlPiUgc3VtbWFyaXplKHJpY2huZXNzPW4oKSkKCmFsZ2FlNTwtbGVmdF9qb2luKGFsZ2FlMixhbGdhZTQpCgojYWxnYWU1PC1hbGdhZTVbd2hpY2goaXMubmEoYWxnYWU1JGRlY2ltYWxMYXRpdHVkZSkpLF0KI2FsZ2FlNTwtYWxnYWU1Wy13aGljaChhbGdhZTUkc2NpZW50aWZpY05hbWU9PSI/IiksXQoKYWxnYWU1WzQsNF08LTEKYWxnYWU1WzExLDRdPC0yCmV4dHJhPC1hbGdhZTVbMzMsXQphbGdhZTU8LWFsZ2FlNVstMzMsXSAjcmVtb3ZlIG91dGxpZXIKCgphbGdhZV9tYXA8LWdnbWFwKGRtYXApICsgZ2VvbV9wb2ludChkYXRhID0gYWxnYWU1LCBtYXBwaW5nID0gYWVzKHggPSBkZWNpbWFsTG9uZ2l0dWRlLCB5ID0gZGVjaW1hbExhdGl0dWRlLCBzaXplPWNvdW50LCBjb2xvcj1yaWNobmVzcykpICsgc2NhbGVfY29sb3JfZ3JhZGllbnQobG93ID0gImdyZWVuIiwgaGlnaD0icmVkIikgKyBndWlkZXMoY29sb3I9Z3VpZGVfY29sb3JiYXIodGl0bGU9IlR5cGUgUmljaG5lc3MiLCksIHNpemU9Z3VpZGVfbGVnZW5kKHRpdGxlPSJJbmRpdmlkdWFsIENvdW50IikpICsgdGhlbWUoYXhpcy50aXRsZT1lbGVtZW50X2JsYW5rKCkpICsgZ2VvbV9wb2ludChkYXRhPWV4dHJhLCBtYXBwaW5nPWFlcyh4ID0gZGVjaW1hbExvbmdpdHVkZSwgeSA9IGRlY2ltYWxMYXRpdHVkZSwgc2l6ZT0zMCwgY29sb3I9MzApKQojYWRkIG91dGxpZXIgYmFjayBpbiBhcyBhIHJlZCBkb3Qgc2l6ZT0zMAoKYWxnYWVfbWFwCgpnZ3NhdmUoYWxnYWVfbWFwLGZpbGVuYW1lPSIuL291dHB1dC9hbGdhZV9tYXAucGRmIikKYGBgCgojIyBNYWNyb2ludmVydGVicmF0ZXMKCiMjIyBJbXBvcnQKYGBge3IgaW52ZXJ0cyBpbXBvcnR9CmludmVydF9zYW1wbGVzPC1yZWFkX2V4Y2VsKHBhdGg9Ii9Vc2Vycy9lcmljL2dvb2dsZV9kcml2ZS9NYXJpbmVHRU8vSW52ZXJ0cy9CS0FORV8wNjMwMTdfRklNUy54bHN4Iiwgc2hlZXQgPSAiU3BlY2ltZW4iLHNraXA9MykKCiNzcG9uZ2VzIHdpbGwgYmUgbG9hZGVkIGhlcmUsIGNsZWFuZWQgdXAsIGFuZCB0aGVuIGpvaW5lZCB3aXRoIHRoZSByZXN0IG9mIHRoZSBpbnZlcnRzCnNwb25nZV9zYW1wbGVzPC1yZWFkX2V4Y2VsKHBhdGg9Ii9Vc2Vycy9lcmljL2dvb2dsZV9kcml2ZS9NYXJpbmVHRU8vU3Bvbmdlcy9WSUNFTlRFX0JJT0JMSVRaMjAxN19TUE9OR0VNRVRBREFUQV9GSU1TLnhsc3giLCBzaGVldCA9ICJTaGVldDEiLHNraXA9MSkKCiNyZW1vdmUgY29sdW1ucyB0aGF0IGRvbid0IGFwcGVhciBpbiBNYXJpbmVHRU8gc2NoZW1hCmludmVydF9zYW1wbGVzPC1pbnZlcnRfc2FtcGxlc1ssLWdyZXAocGF0dGVybiA9ICJeWCIseCA9IG5hbWVzKGludmVydF9zYW1wbGVzKSxwZXJsPVQpXQpzcG9uZ2Vfc2FtcGxlczwtc3BvbmdlX3NhbXBsZXNbLC1ncmVwKHBhdHRlcm4gPSAiXlgiLHggPSBuYW1lcyhzcG9uZ2Vfc2FtcGxlcykscGVybD1UKV0KCiNyZW1vdmUgcmVjb3JkcyB3aXRob3V0IG9jY3VycmVuY2VJRHMgKHRlbXAgYmVmb3JlIGZpbmFsIGRhdGFzZXQpCmludmVydF9zYW1wbGVzPC1pbnZlcnRfc2FtcGxlc1std2hpY2goaXMubmEoaW52ZXJ0X3NhbXBsZXMkc2NpZW50aWZpY05hbWUpKSxdCnNwb25nZV9zYW1wbGVzPC1zcG9uZ2Vfc2FtcGxlc1std2hpY2goaXMubmEoc3BvbmdlX3NhbXBsZXMkc2NpZW50aWZpY05hbWUpKSxdCgojY2hhbmdlIGFsbCBlbXB0eSBjb2x1bW5zIGZyb20gbG9naWNhbCB0byBjaGFyYWN0ZXIgY2xhc3MKaW52ZXJ0X3NhbXBsZXNbc2FwcGx5KGludmVydF9zYW1wbGVzLCBpcy5sb2dpY2FsKV0gPC0gbGFwcGx5KGludmVydF9zYW1wbGVzW3NhcHBseShpbnZlcnRfc2FtcGxlcywgaXMubG9naWNhbCldLCAgYXMuY2hhcmFjdGVyKQoKCnNwb25nZV9zYW1wbGVzW3NhcHBseShzcG9uZ2Vfc2FtcGxlcywgaXMubG9naWNhbCldIDwtIGxhcHBseShzcG9uZ2Vfc2FtcGxlc1tzYXBwbHkoc3BvbmdlX3NhbXBsZXMsIGlzLmxvZ2ljYWwpXSwgIGFzLmNoYXJhY3RlcikKCnNwb25nZV9zYW1wbGVzJHBoeWx1bVt3aGljaChpcy5uYShzcG9uZ2Vfc2FtcGxlcyRwaHlsdW0pKV08LSJQb3JpZmVyYSIKc3BvbmdlX3NhbXBsZXMkZXZlbnRJRDwtc3RyX3JlcGxhY2Uoc3BvbmdlX3NhbXBsZXMkZXZlbnRJRCxwYXR0ZXJuPSItIiwgcmVwbGFjZW1lbnQ9IiIpCgoKaW52ZXJ0X3NhbXBsZXM8LWZ1bGxfam9pbihpbnZlcnRfc2FtcGxlcyxzcG9uZ2Vfc2FtcGxlcykKYGBgCgojIyMgVGF4b25vbWl6ZQoKVGhpcyBjb2RlIHdpbGwgcG9wdWxhdGUgYHRheG9uUmFua2Agd2l0aCB0aGUgbG93ZXN0IGtub3duIHRheG9ub21pYyBjYXRlZ29yeQoKYGBge3IgSW52ZXJ0cyBUYXhvbm9taXplfQoKaW52ZXJ0X3NhbXBsZXMkdGF4b25SYW5rW3doaWNoKCFpcy5uYShpbnZlcnRfc2FtcGxlcyRwaHlsdW0pKV08LSJwaHlsdW0iCmludmVydF9zYW1wbGVzJHRheG9uUmFua1t3aGljaCghaXMubmEoaW52ZXJ0X3NhbXBsZXMkY2xhc3MpKV08LSJjbGFzcyIKaW52ZXJ0X3NhbXBsZXMkdGF4b25SYW5rW3doaWNoKCFpcy5uYShpbnZlcnRfc2FtcGxlcyRzdWJjbGFzcykpXTwtInN1YmNsYXNzIgppbnZlcnRfc2FtcGxlcyR0YXhvblJhbmtbd2hpY2goIWlzLm5hKGludmVydF9zYW1wbGVzJG9yZGVyKSldPC0ib3JkZXIiCmludmVydF9zYW1wbGVzJHRheG9uUmFua1t3aGljaCghaXMubmEoaW52ZXJ0X3NhbXBsZXMkc3Vib3JkZXIpKV08LSJzdWJvcmRlciIKaW52ZXJ0X3NhbXBsZXMkdGF4b25SYW5rW3doaWNoKCFpcy5uYShpbnZlcnRfc2FtcGxlcyRzdXBlcmZhbWlseSkpXTwtInN1cGVyZmFtaWx5IgppbnZlcnRfc2FtcGxlcyR0YXhvblJhbmtbd2hpY2goIWlzLm5hKGludmVydF9zYW1wbGVzJGZhbWlseSkpXTwtImZhbWlseSIKaW52ZXJ0X3NhbXBsZXMkdGF4b25SYW5rW3doaWNoKCFpcy5uYShpbnZlcnRfc2FtcGxlcyRzdWJmYW1pbHkpKV08LSJzdWJmYW1pbHkiCmludmVydF9zYW1wbGVzJHRheG9uUmFua1t3aGljaCghaXMubmEoaW52ZXJ0X3NhbXBsZXMkZ2VudXMpKV08LSJnZW51cyIKaW52ZXJ0X3NhbXBsZXMkdGF4b25SYW5rW3doaWNoKCFpcy5uYShpbnZlcnRfc2FtcGxlcyRzcGVjaWVzKSldPC0ic3BlY2llcyIKaW52ZXJ0X3NhbXBsZXMkdGF4b25SYW5rW2dyZXAoInNwXFwuIixpbnZlcnRfc2FtcGxlcyRzcGVjaWVzKV08LSJnZW51cyIKCgoKYGBgCgoKIyMjIEZvcm1hdCBzYW1wbGVzIHRvIHNjaGVtYQoKYGBge3IgZm9ybWF0IGludmVydCBzYW1wbGVzfQojY2hhbmdlIGFsbCBlbXB0eSBjb2x1bW5zIGZyb20gbG9naWNhbCB0byBjaGFyYWN0ZXIgY2xhc3MgbW92ZWQgdGhpcyB1cAojaW52ZXJ0X3NhbXBsZXNbc2FwcGx5KGludmVydF9zYW1wbGVzLCBpcy5sb2dpY2FsKV0gPC0gI2xhcHBseShpbnZlcnRfc2FtcGxlc1tzYXBwbHkoaW52ZXJ0X3NhbXBsZXMsIGlzLmxvZ2ljYWwpXSwgIGFzLmNoYXJhY3RlcikKCiMgY2xhc3MoaW52ZXJ0X3NhbXBsZXMkb2NjdXJyZW5jZUlEKQojIGNsYXNzKGludmVydF9zYW1wbGVzJHNjaWVudGlmaWNOYW1lKSAjZXZlbnR1YWxseSBwYXJzZSB0aGlzIGludG8gdGF4b24gY2F0ZWdvcmllcz8KIyBjbGFzcyhpbnZlcnRfc2FtcGxlcyR0YXhvblJhbmspICN1c2luZyB0aGlzCgppbnZlcnRfc2FtcGxlcyRiYXNpc09mUmVjb3JkPC0ic3BlY2ltZW4iCmludmVydF9zYW1wbGVzJG9yZ2FuaXNtU2NvcGU8LSJvcmdhbmlzbSIKCiNyZW1vdmUgZXZlbnRJRHMgdGhhdCBoYXZlIHR3byBwb3NzaWJpbGl0aWVzLCBhc3N1bWUgaXQgaXMgdGhlIGZpcnN0IG9uZSBmb3Igbm93CmludmVydF9zYW1wbGVzJGV2ZW50SUQ8LWdzdWIocGF0dGVybj0iKFxcdykgb3IgXFx3IixyZXBsYWNlbWVudD0iXFwxIix4PSBpbnZlcnRfc2FtcGxlcyRldmVudElELHBlcmw9VCkKCiNyZW1vdmUgdGhlIEEsQixDIGV0Yy4gZnJvbSB0aGUgZW5kcyBvZiBldmVudElEcyB1bnRpbCB0aGUgSVogdGVhbSBmaXhlcyB0aGVtIHVwIHRvIGJlIG1lYW5pbmdmdWwKaW52ZXJ0X3NhbXBsZXMkZXZlbnRJRDwtc3RyX3JlcGxhY2Uoc3RyaW5nPWludmVydF9zYW1wbGVzJGV2ZW50SUQsIHBhdHRlcm49IihLQU5cXHdcXGRcXGRcXGQpW0EtWl0iLHJlcGxhY2VtZW50PSJcXDEiKQoKI2ZpeCBhcm1zIGV2ZW50SURzCmludmVydF9zYW1wbGVzJGV2ZW50SURbZ3JlcChwYXR0ZXJuPSJLQU5FTyIsaW52ZXJ0X3NhbXBsZXMkZXZlbnRJRCldPC1zdHJfcmVwbGFjZShzdHJpbmc9aW52ZXJ0X3NhbXBsZXMkZXZlbnRJRFtncmVwKHBhdHRlcm49IktBTkVPIixpbnZlcnRfc2FtcGxlcyRldmVudElEKV0scGF0dGVybj0iS0FORU9cXGQoXFxkXFxkKSIsIHJlcGxhY2VtZW50PSJLQU5FT18yMDE3X0FSTVNcXDEiKQoKCmludmVydF9zYW1wbGVzJGlkZW50aWZpZWRCeTwtIlBhdWxheSwgR3VzdGF2IiAjIGZvciBub3cuIGRvbid0IGtub3cgaWYgdGhleSBrZXB0IHRoaXMgaW5mbwojYXNzdW1lIHRoYXQgYmxhbmsgY291bnRzIGhhZCAxIGluZGl2aWR1YWwgZm9yIG5vdwppbnZlcnRfc2FtcGxlcyRpbmRpdmlkdWFsQ291bnRbaXMubmEoaW52ZXJ0X3NhbXBsZXMkaW5kaXZpZHVhbENvdW50KV08LTEKaW52ZXJ0X3NhbXBsZXMkaW5zdGl0dXRpb25JRDwtIkZMTU5IIgoKCgpgYGAKCiMjIyBKb2luIHRoZSBldmVudCBkYXRhIG9udG8gdGhlIG9jY3VycmVuY2UgZGF0YQoKYGBge3IgaW52ZXJ0IGpvaW59CmludmVydDwtbGVmdF9qb2luKGludmVydF9zYW1wbGVzLGV2ZW50cyxieT0iZXZlbnRJRCIpCmBgYAoKIyMjIE1ha2UgQSBNYXAKYGBge3IgaW52ZXJ0IG1hcHN9CiNieSBpbmRpdmlkdWFsCmludmVydDI8LWludmVydCAlPiUgZ3JvdXBfYnkoZGVjaW1hbExhdGl0dWRlLCBkZWNpbWFsTG9uZ2l0dWRlKSAlPiUgc3VtbWFyaXplKGluZGl2aWR1YWxDb3VudD1zdW0oaW5kaXZpZHVhbENvdW50LG5hLnJtID0gVCkpIAoKI2J5IHNwZWNpZXMKaW52ZXJ0MyA8LSBpbnZlcnQgJT4lIGdyb3VwX2J5KHNjaWVudGlmaWNOYW1lLCBkZWNpbWFsTGF0aXR1ZGUsIGRlY2ltYWxMb25naXR1ZGUpICU+JSBzdW1tYXJpemUoY291bnQ9bigpKQoKI3JpY2huZXNzCmludmVydDQ8LWludmVydDMgJT4lIGdyb3VwX2J5KGRlY2ltYWxMYXRpdHVkZSxkZWNpbWFsTG9uZ2l0dWRlKSAlPiUgc3VtbWFyaXplKHJpY2huZXNzPW4oKSkKCmludmVydDU8LWxlZnRfam9pbihpbnZlcnQyLGludmVydDQpCgoKCgppbnZlcnRfbWFwPC1nZ21hcChkbWFwKSArIGdlb21fcG9pbnQoZGF0YSA9IGludmVydDVbLWMobGVuZ3RoKGludmVydDUkcmljaG5lc3MpLTEsbGVuZ3RoKGludmVydDUkcmljaG5lc3MpKSxdLCBtYXBwaW5nID0gYWVzKHggPSBkZWNpbWFsTG9uZ2l0dWRlLCB5ID0gZGVjaW1hbExhdGl0dWRlLCBzaXplPWluZGl2aWR1YWxDb3VudCwgY29sb3I9cmljaG5lc3MpKSArIHNjYWxlX2NvbG9yX2dyYWRpZW50KGxvdyA9ICJncmVlbiIsIGhpZ2g9InJlZCIpICsgZ3VpZGVzKGNvbG9yPWd1aWRlX2NvbG9yYmFyKHRpdGxlPSJUeXBlIFJpY2huZXNzIiwpLCBzaXplPWd1aWRlX2xlZ2VuZCh0aXRsZT0iSW5kaXZpZHVhbCBDb3VudCIpKSArIHRoZW1lKGF4aXMudGl0bGU9ZWxlbWVudF9ibGFuaygpKSAKCmludmVydF9tYXAKCmdnc2F2ZShpbnZlcnRfbWFwLGZpbGVuYW1lPSIuL291dHB1dC9pbnZlcnRfbWFwLnBkZiIpCgojY3JlYXRlIGEgdmVjdG9yIG9mIHRoZSBldmVudElEcyBub3QgZmluZGluZyBhIG1hdGNoIGluIHRoZSBldmVudHMgZGF0YWJhc2UKYmFkX2V2ZW50SURzPC1pbnZlcnQkZXZlbnRJRFt3aGljaChpcy5uYShpbnZlcnQkZGVjaW1hbExhdGl0dWRlKSldCmBgYAoKIyMjIE1ha2UgQSBTcG9uZ2UgTWFwCgpgYGB7ciBzcG9uZ2UgbWFwc30Kc3BvbmdlPC1pbnZlcnRbd2hpY2goaW52ZXJ0JHBoeWx1bT09IlBvcmlmZXJhIiksXQojYnkgaW5kaXZpZHVhbApzcG9uZ2UyPC1zcG9uZ2UgJT4lIGdyb3VwX2J5KGRlY2ltYWxMYXRpdHVkZSwgZGVjaW1hbExvbmdpdHVkZSkgJT4lIHN1bW1hcml6ZShpbmRpdmlkdWFsQ291bnQ9c3VtKGluZGl2aWR1YWxDb3VudCxuYS5ybSA9IFQpKSAKCiNieSBzcGVjaWVzCnNwb25nZTMgPC0gc3BvbmdlICU+JSBncm91cF9ieShzY2llbnRpZmljTmFtZSwgZGVjaW1hbExhdGl0dWRlLCBkZWNpbWFsTG9uZ2l0dWRlKSAlPiUgc3VtbWFyaXplKGNvdW50PW4oKSkKCiNyaWNobmVzcwpzcG9uZ2U0PC1zcG9uZ2UzICU+JSBncm91cF9ieShkZWNpbWFsTGF0aXR1ZGUsZGVjaW1hbExvbmdpdHVkZSkgJT4lIHN1bW1hcml6ZShyaWNobmVzcz1uKCkpCgpzcG9uZ2U1PC1sZWZ0X2pvaW4oc3BvbmdlMixzcG9uZ2U0KQoKCgpzcG9uZ2VfbWFwPC1nZ21hcChkbWFwKSArIGdlb21fcG9pbnQoZGF0YSA9IHNwb25nZTVbLWMoNjEsNjIpLF0sIG1hcHBpbmcgPSBhZXMoeCA9IGRlY2ltYWxMb25naXR1ZGUsIHkgPSBkZWNpbWFsTGF0aXR1ZGUsIHNpemU9aW5kaXZpZHVhbENvdW50LCBjb2xvcj1yaWNobmVzcykpICsgc2NhbGVfY29sb3JfZ3JhZGllbnQobG93ID0gImdyZWVuIiwgaGlnaD0icmVkIikgKyBndWlkZXMoY29sb3I9Z3VpZGVfY29sb3JiYXIodGl0bGU9IlR5cGUgUmljaG5lc3MiLCksIHNpemU9Z3VpZGVfbGVnZW5kKHRpdGxlPSJJbmRpdmlkdWFsIENvdW50IikpICsgdGhlbWUoYXhpcy50aXRsZT1lbGVtZW50X2JsYW5rKCkpIAoKc3BvbmdlX21hcAoKZ2dzYXZlKHNwb25nZV9tYXAsZmlsZW5hbWU9Ii4vb3V0cHV0L3Nwb25nZV9tYXAucGRmIikKCmBgYAoKIyMgTWVpb2ZhdW5hCgojIyMgSW1wb3J0CmBgYHtyIGltcG9ydCBtZWlvZmF1bmF9CiNub3RlIG1laW8gZGF0YSBzdGlsbCBuZWVkIHNvbWUgY2xlYW5pbmcsIGluY2x1ZGluZyBpbXBvcnRpbmcgc29tZSBzdGF0aW9ucyBmcm9tIGludmVydHMgYW5kIGZpc2gsIGFuZCBmaXhpbmcgdXAgZXZlbnRJRHMgdG8gaGF2ZSAzIGRpZ2l0cyBpbnN0ZWFkIG9mIDIuIFRoZXJlIGFyZSAyNyBzcGVjaW1lbnMgdGhhdCBkbyBub3QgaGF2ZSBzdGF0aW9uIGluZm9ybWF0aW9uIGJlY2F1c2Ugb2YgdGhpcy4KCm1laW9fc2FtcGxlczwtcmVhZF9leGNlbChwYXRoPSIvVXNlcnMvZXJpYy9nb29nbGVfZHJpdmUvTWFyaW5lR0VPL01laW9mYXVuYS9IYXdhaWkyMDE3X21laW9mYXVuYV9NYXJpbmVHRU8ueGxzeCIsIHNoZWV0ID0gInNwZWNpbWVuIGRhdGEiLHNraXA9MSkKCiNyZW1vdmUgY29sdW1ucyB0aGF0IGRvbid0IGFwcGVhciBpbiBNYXJpbmVHRU8gc2NoZW1hCm1laW9fc2FtcGxlczwtbWVpb19zYW1wbGVzWywtZ3JlcChwYXR0ZXJuID0gIl5YIix4ID0gbmFtZXMobWVpb19zYW1wbGVzKSxwZXJsPVQpXQoKI2FkZCBvY2N1cnJlbmNlIElEcyB0byBvbmUgaW52ZXN0aWdhdG9ycyBzYW1wbGVzIC0gdGhpcyBoYXMgYmVlbiB0YWtlbiBjYXJlIG9mIG5vdwojbWVpb19zYW1wbGVzJG9jY3VycmVuY2VJRFt3aGljaChpcy5uYShtZWlvX3NhbXBsZXMkb2NjdXJyZW5jZUlEKSldPC0iVUoiIAojbWFrZSBvY2N1cnJlbmNlIElEcyB1bmlxdWUKI21laW9fc2FtcGxlcyRvY2N1cnJlbmNlSUQ8LW1ha2UudW5pcXVlKG1laW9fc2FtcGxlcyRvY2N1cnJlbmNlSUQsIHNlcD0iXyIpCgoKYGBgCgoKIyMjIEZvcm1hdCBzYW1wbGVzIHRvIHNjaGVtYQoKYGBge3IgZm9ybWF0IG1laW9mYXVuYSBzYW1wbGVzfQojY2hhbmdlIGFsbCBlbXB0eSBjb2x1bW5zIGZyb20gbG9naWNhbCB0byBjaGFyYWN0ZXIgY2xhc3MKbWVpb19zYW1wbGVzW3NhcHBseShtZWlvX3NhbXBsZXMsIGlzLmxvZ2ljYWwpXSA8LSBsYXBwbHkobWVpb19zYW1wbGVzW3NhcHBseShtZWlvX3NhbXBsZXMsIGlzLmxvZ2ljYWwpXSwgIGFzLmNoYXJhY3RlcikKCm1laW9fc2FtcGxlcyRiYXNpc29mUmVjb3JkPC0ic3BlY2ltZW4iICNjaGVjayB3aXRoIEZyZXkgdGhhdCB0aGlzIGlzIGNvcnJlY3QKbWVpb19zYW1wbGVzJGluc3RpdHV0aW9uSUQ8LSJVU05NIgoKIyBjbGFzcyhtZWlvX3NhbXBsZXMkc2NpZW50aWZpY05hbWUpICNldmVudHVhbGx5IHBhcnNlIHRoaXMgaW50byB0YXhvbiBjYXRlZ29yaWVzPwojIGNsYXNzKG1laW9fc2FtcGxlcyR0YXhvblJhbmspICN1c2luZyB0aGlzCiMgY2xhc3MobWVpb19zYW1wbGVzJG9jY3VycmVuY2VJRCkKIyBjbGFzcyhtZWlvX3NhbXBsZXMkY2F0YWxvZ051bWJlcikKIyBjbGFzcyhtZWlvX3NhbXBsZXMkb3RoZXJDYXRhbG9nTnVtYmVycykKIyBjbGFzcyhtZWlvX3NhbXBsZXMkb3JnYW5pc21TY29wZSkKIyBjbGFzcyhtZWlvX3NhbXBsZXMkZXZlbnRJRCkKIyBjbGFzcyhtZWlvX3NhbXBsZXMkaWRlbnRpZmllZEJ5KQojIGNsYXNzKG1laW9fc2FtcGxlcyRpbmRpdmlkdWFsQ291bnQpCgoKYGBgCgojIyMgSm9pbiB0aGUgZXZlbnQgZGF0YSBvbnRvIHRoZSBvY2N1cnJlbmNlIGRhdGEKCmBgYHtyIG1laW9mYXVuYSBqb2lufQptZWlvPC1sZWZ0X2pvaW4obWVpb19zYW1wbGVzLG1laW9fZXZlbnRzLGJ5PSJldmVudElEIikKYGBgCgojIyMgTWFrZSBBIE1hcApgYGB7ciBtZWlvZmF1bmEgbWFwc30KI2J5IGluZGl2aWR1YWwKbWVpbzI8LW1laW8gJT4lIGdyb3VwX2J5KGRlY2ltYWxMYXRpdHVkZSwgZGVjaW1hbExvbmdpdHVkZSkgJT4lIHN1bW1hcml6ZShpbmRpdmlkdWFsQ291bnQ9c3VtKGluZGl2aWR1YWxDb3VudCxuYS5ybSA9IFQpKSAKCiNieSBzcGVjaWVzCm1laW8zIDwtIG1laW8gJT4lIGdyb3VwX2J5KHNjaWVudGlmaWNOYW1lLCBkZWNpbWFsTGF0aXR1ZGUsIGRlY2ltYWxMb25naXR1ZGUpICU+JSBzdW1tYXJpemUoY291bnQ9bigpKQoKI3JpY2huZXNzCm1laW80PC1tZWlvMyAlPiUgZ3JvdXBfYnkoZGVjaW1hbExhdGl0dWRlLGRlY2ltYWxMb25naXR1ZGUpICU+JSBzdW1tYXJpemUocmljaG5lc3M9bigpKQoKbWVpbzU8LWxlZnRfam9pbihtZWlvMixtZWlvNCkKCgoKCm1laW9fbWFwPC1nZ21hcChkbWFwKSArIGdlb21fcG9pbnQoZGF0YSA9IG1laW81LCBtYXBwaW5nID0gYWVzKHggPSBkZWNpbWFsTG9uZ2l0dWRlLCB5ID0gZGVjaW1hbExhdGl0dWRlLCBzaXplPWluZGl2aWR1YWxDb3VudCwgY29sb3I9cmljaG5lc3MpKSArIHNjYWxlX2NvbG9yX2dyYWRpZW50KGxvdyA9ICJncmVlbiIsIGhpZ2g9InJlZCIpICsgZ3VpZGVzKGNvbG9yPWd1aWRlX2NvbG9yYmFyKHRpdGxlPSJUeXBlIFJpY2huZXNzIiwpLCBzaXplPWd1aWRlX2xlZ2VuZCh0aXRsZT0iSW5kaXZpZHVhbCBDb3VudCIpKSArIHRoZW1lKGF4aXMudGl0bGU9ZWxlbWVudF9ibGFuaygpKSAKCm1laW9fbWFwCgpnZ3NhdmUobWVpb19tYXAsZmlsZW5hbWU9Ii4vb3V0cHV0L21laW9fbWFwLnBkZiIpCmBgYAoKIyMgQVJNUwoKIyMjIEltcG9ydApgYGB7ciBpbXBvcnQgYXJtc30KYXJtc19zYW1wbGVzPC1yZWFkX2V4Y2VsKHBhdGg9Ii9Vc2Vycy9lcmljL2dvb2dsZV9kcml2ZS9NYXJpbmVHRU8vQVJNUy9NYXJpbmVHRU9ISV9iaW9hc3Nlc3NtZW50X21hc3Rlci1BUk1TLnhsc3giLCBzaGVldCA9ICJTYW1wbGUiKQoKYGBgCgoKIyMjIEZvcm1hdCBzYW1wbGVzIHRvIHNjaGVtYQoKYGBge3IgZm9ybWF0IGFybXMgc2FtcGxlc30KI2NoYW5nZSBhbGwgZW1wdHkgY29sdW1ucyBmcm9tIGxvZ2ljYWwgdG8gY2hhcmFjdGVyIGNsYXNzCmFybXNfc2FtcGxlc1tzYXBwbHkoYXJtc19zYW1wbGVzLCBpcy5sb2dpY2FsKV0gPC0gbGFwcGx5KGFybXNfc2FtcGxlc1tzYXBwbHkoYXJtc19zYW1wbGVzLCBpcy5sb2dpY2FsKV0sICBhcy5jaGFyYWN0ZXIpCgojIGNsYXNzKGFybXNfc2FtcGxlcyRvY2N1cnJlbmNlSUQpCiMgY2xhc3MoYXJtc19zYW1wbGVzJGJhc2lzb2ZSZWNvcmQpCiMgY2xhc3MoYXJtc19zYW1wbGVzJGNhdGFsb2dOdW1iZXIpCiMgY2xhc3MoYXJtc19zYW1wbGVzJG90aGVyQ2F0YWxvZ051bWJlcnMpCiMgY2xhc3MoYXJtc19zYW1wbGVzJG9yZ2FuaXNtU2NvcGUpICN3ZXJlIHRoZXJlIHNvbWUgc2x1cnJpZXMgdG9vPwojIGNsYXNzKGFybXNfc2FtcGxlcyRldmVudElEKQojIGNsYXNzKGFybXNfc2FtcGxlcyRzY2llbnRpZmljTmFtZSkgI2V2ZW50dWFsbHkgcGFyc2UgdGhpcyBpbnRvIHRheG9uIGNhdGVnb3JpZXM/CiMgY2xhc3MoYXJtc19zYW1wbGVzJHRheG9uUmFuaykgI3VzaW5nIHRoaXMKIyBjbGFzcyhhcm1zX3NhbXBsZXMkaWRlbnRpZmllZEJ5KQojIGNsYXNzKGFybXNfc2FtcGxlcyRpbmRpdmlkdWFsQ291bnQpCgojIGNoYW5nZSBOQXMgZm9yIGluZGl2aWR1YWxDb3VudCB0byAxIGZvciBub3cKYXJtc19zYW1wbGVzJGluZGl2aWR1YWxDb3VudFt3aGljaChpcy5uYShhcm1zX3NhbXBsZXMkaW5kaXZpZHVhbENvdW50KSldPC0xCgphcm1zX3NhbXBsZXMkaW5zdGl0dXRpb25JRDwtIlVTTk0iCgpgYGAKCiMjIyBKb2luIHRoZSBldmVudCBkYXRhIG9udG8gdGhlIG9jY3VycmVuY2UgZGF0YQoKYGBge3IgYXJtcyBqb2lufQphcm1zPC1sZWZ0X2pvaW4oYXJtc19zYW1wbGVzLGFybXNfZXZlbnRzLGJ5PSJldmVudElEIikKYGBgCgojIyMgTWFrZSBBIE1hcApgYGB7ciBhcm1zIG1hcHN9CiNieSBpbmRpdmlkdWFsCmFybXMyPC1hcm1zICU+JSBncm91cF9ieShkZWNpbWFsTGF0aXR1ZGUsIGRlY2ltYWxMb25naXR1ZGUpICU+JSBzdW1tYXJpemUoaW5kaXZpZHVhbENvdW50PXN1bShpbmRpdmlkdWFsQ291bnQsbmEucm0gPSBUKSkgCgojYnkgc3BlY2llcwphcm1zMyA8LSBhcm1zICU+JSBncm91cF9ieShzY2llbnRpZmljTmFtZSwgZGVjaW1hbExhdGl0dWRlLCBkZWNpbWFsTG9uZ2l0dWRlKSAlPiUgc3VtbWFyaXplKGNvdW50PW4oKSkKCiNyaWNobmVzcwphcm1zNDwtYXJtczMgJT4lIGdyb3VwX2J5KGRlY2ltYWxMYXRpdHVkZSxkZWNpbWFsTG9uZ2l0dWRlKSAlPiUgc3VtbWFyaXplKHJpY2huZXNzPW4oKSkKCmFybXM1PC1sZWZ0X2pvaW4oYXJtczIsYXJtczQpCgoKCgphcm1zX21hcDwtZ2dtYXAoZG1hcCkgKyBnZW9tX3BvaW50KGRhdGEgPSBhcm1zNSwgbWFwcGluZyA9IGFlcyh4ID0gZGVjaW1hbExvbmdpdHVkZSwgeSA9IGRlY2ltYWxMYXRpdHVkZSwgc2l6ZT1pbmRpdmlkdWFsQ291bnQsIGNvbG9yPXJpY2huZXNzKSkgKyBzY2FsZV9jb2xvcl9ncmFkaWVudChsb3cgPSAiZ3JlZW4iLCBoaWdoPSJyZWQiKSArIGd1aWRlcyhjb2xvcj1ndWlkZV9jb2xvcmJhcih0aXRsZT0iVHlwZSBSaWNobmVzcyIsKSwgc2l6ZT1ndWlkZV9sZWdlbmQodGl0bGU9IkluZGl2aWR1YWwgQ291bnQiKSkgKyB0aGVtZShheGlzLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSkgCgphcm1zX21hcAoKZ2dzYXZlKGFybXNfbWFwLGZpbGVuYW1lPSIuL291dHB1dC9hcm1zX21hcC5wZGYiKQpgYGAKCgojIyBWaXN1YWwgVHJhbnNlY3RzCgojIyMgSW1wb3J0CmBgYHtyIHRyYW5zZWN0cyBpbXBvcnR9Cgp0cmFuc19zYW1wbGVzPC1yZWFkX2V4Y2VsKHBhdGg9Ii9Vc2Vycy9lcmljL2dvb2dsZV9kcml2ZS9NYXJpbmVHRU8vVHJhbnNlY3RzL2Jpb2Fzc2Vzc21lbnRfS0FOVi54bHN4Iiwgc2hlZXQgPSAiU2FtcGxlIikKCnRyYW5zX29yZ2FuaXNtX3Bob3RvczwtcmVhZF9leGNlbChwYXRoPSIvVXNlcnMvZXJpYy9nb29nbGVfZHJpdmUvTWFyaW5lR0VPL1RyYW5zZWN0cy9LQU5WX3Bob3RvLXZvdWNoZXJzXzIwMTcwNzEyLnhsc3giLCBzaGVldCA9ICJTaGVldDEiKQpgYGAKCiMjIyBGb3JtYXQsIGNvbGxhcHNlIGFuZCBtZXJnZSB0aGUgbWVkaWEgZmllbGRzCgojIyMgT3JnYW5pc20gcGhvdG9zCmBgYHtyIHRyYW5zZWN0IHBob3RvIGZpZWxkc30KIyBvcmdhbmlzbSBwaG90b3MKCiMjIGRlbGV0ZSB0aGUgZmllbGQgdG8gYmUgYWRkZWQgbGF0ZXIKdHJhbnNfc2FtcGxlcyRhc3NvY2lhdGVkTWVkaWE8LU5VTEwKCiNwb3Agb2ZmIHRoZSBldmVudElEIGFnYWluIGludG8gaXRzIG93biBmaWVsZAp0cmFuc19vcmdhbmlzbV9waG90b3MkZXZlbnRJRDwtc3ViKHBhdHRlcm49IihLQU5WXFxkXFxkXFxkKV8uKyIscmVwbGFjZW1lbnQgPSAiXFwxIiwgdHJhbnNfb3JnYW5pc21fcGhvdG9zJGFzc29jaWF0ZWRNZWRpYSwgcGVybD1UKQoKI3BvcCBvZmYgdGhlIHNwZWNpZXMgbmFtZSBpbnRvIGl0cyBvd24gZmllbGQKdHJhbnNfb3JnYW5pc21fcGhvdG9zJHNjaWVudGlmaWNOYW1lPC1zdWIocGF0dGVybj0iLitfKFxcZHs4fSlfKFxcdystW2Etel0rKV8uKyIsIHJlcGxhY2VtZW50ID0gIlxcMiIsIHRyYW5zX29yZ2FuaXNtX3Bob3RvcyRhc3NvY2lhdGVkTWVkaWEscGVybD1UKQp0cmFuc19vcmdhbmlzbV9waG90b3Mkc2NpZW50aWZpY05hbWU8LXN1YihwYXR0ZXJuPSItIiwgcmVwbGFjZW1lbnQ9IiAiLHggPSB0cmFuc19vcmdhbmlzbV9waG90b3Mkc2NpZW50aWZpY05hbWUpCgojcG9wIG9mZiB0aGUgaW5pdGlhbHMgb2YgdGhlIGNvbGxlY3RvciwgYW5kIHJlcGxhY2Ugd2l0aCBmdWxsIG5hbWUKdHJhbnNfb3JnYW5pc21fcGhvdG9zJGlkZW50aWZpZWRCeTwtc3RyX2V4dHJhY3QocGF0dGVybj0iWkZ8UlciLCBzdHJpbmc9dHJhbnNfb3JnYW5pc21fcGhvdG9zJGFzc29jaWF0ZWRNZWRpYSkKdHJhbnNfb3JnYW5pc21fcGhvdG9zJGlkZW50aWZpZWRCeVt3aGljaCh0cmFuc19vcmdhbmlzbV9waG90b3MkaWRlbnRpZmllZEJ5PT0iWkYiKV08LSJaYWNoIEZvbHR6Igp0cmFuc19vcmdhbmlzbV9waG90b3MkaWRlbnRpZmllZEJ5W3doaWNoKHRyYW5zX29yZ2FuaXNtX3Bob3RvcyRpZGVudGlmaWVkQnk9PSJSVyIpXTwtIlJvc3MgV2hpcHBvIgoKI3VzZSBkZHBseSB0byBsdW1wIGFsbCBhc3NvY2lhdGVkTWVkaWEgaW50byBhIHNpbmdsZSBmaWVsZCwgc2VwYXJhdGVkIGJ5IGEgfAp0cmFuc19hc3NvY2lhdGVkTWVkaWE8LWRkcGx5KHRyYW5zX29yZ2FuaXNtX3Bob3RvcywgYygiZXZlbnRJRCIsInNjaWVudGlmaWNOYW1lIiwiaWRlbnRpZmllZEJ5IiksIHRyYW5zZm9ybSwgYXNzb2NpYXRlZE1lZGlhID0gcGFzdGUoYXNzb2NpYXRlZE1lZGlhLCBjb2xsYXBzZSA9ICJ8IikpCgojcmVtb3ZlIGFsbCBidXQgdGhlIGZpcnN0IGluc3RhbmNlCnRyYW5zX2Fzc29jaWF0ZWRNZWRpYTwtdHJhbnNfYXNzb2NpYXRlZE1lZGlhWyFkdXBsaWNhdGVkKHRyYW5zX2Fzc29jaWF0ZWRNZWRpYSRhc3NvY2lhdGVkTWVkaWEpLF0KCnRyYW5zX3NhbXBsZXM8LWxlZnRfam9pbih0cmFuc19zYW1wbGVzLCB0cmFuc19hc3NvY2lhdGVkTWVkaWEsIGJ5PWMoImV2ZW50SUQiLCJzY2llbnRpZmljTmFtZSIsImlkZW50aWZpZWRCeSIpKQoKYGBgCgojIyMgRm9ybWF0IHNhbXBsZXMgdG8gc2NoZW1hCgpgYGB7ciBmb3JtYXQgdHJhbnNlY3Qgc2FtcGxlc30KI2NoYW5nZSBhbGwgZW1wdHkgY29sdW1ucyBmcm9tIGxvZ2ljYWwgdG8gY2hhcmFjdGVyIGNsYXNzCnRyYW5zX3NhbXBsZXNbc2FwcGx5KHRyYW5zX3NhbXBsZXMsIGlzLmxvZ2ljYWwpXSA8LSBsYXBwbHkodHJhbnNfc2FtcGxlc1tzYXBwbHkodHJhbnNfc2FtcGxlcywgaXMubG9naWNhbCldLCAgYXMuY2hhcmFjdGVyKQoKIyBjbGFzcyh0cmFuc19zYW1wbGVzJG9jY3VycmVuY2VJRCkKIyBjbGFzcyh0cmFuc19zYW1wbGVzJGJhc2lzb2ZSZWNvcmQpCiMgY2xhc3ModHJhbnNfc2FtcGxlcyRjYXRhbG9nTnVtYmVyKQojIGNsYXNzKHRyYW5zX3NhbXBsZXMkb3RoZXJDYXRhbG9nTnVtYmVycykKIyBjbGFzcyh0cmFuc19zYW1wbGVzJG9yZ2FuaXNtU2NvcGUpCiMgY2xhc3ModHJhbnNfc2FtcGxlcyRldmVudElEKQojIGNsYXNzKHRyYW5zX3NhbXBsZXMkc2NpZW50aWZpY05hbWUpICNldmVudHVhbGx5IHBhcnNlIHRoaXMgaW50byB0YXhvbiBjYXRlZ29yaWVzPwojIGNsYXNzKHRyYW5zX3NhbXBsZXMkdGF4b25SYW5rKSAjdXNpbmcgdGhpcwojIGNsYXNzKHRyYW5zX3NhbXBsZXMkaWRlbnRpZmllZEJ5KQojIGNsYXNzKHRyYW5zX3NhbXBsZXMkaW5kaXZpZHVhbENvdW50KQoKdHJhbnNfc2FtcGxlcyRpbnN0aXR1dGlvbklEPC0iVVNOTSIKCgoKCmBgYAoKIyMjIEpvaW4gdGhlIGV2ZW50IGRhdGEgb250byB0aGUgb2NjdXJyZW5jZSBkYXRhCgpgYGB7ciBqb2luIHRyYW5zZWN0c30KdHJhbnM8LWxlZnRfam9pbih0cmFuc19zYW1wbGVzLHRyYW5zX2V2ZW50cyxieT0iZXZlbnRJRCIpCmBgYAoKIyMjIE1ha2UgQSBNYXAKYGBge3IgdHJhbnNlY3QgbWFwc30KI2J5IGluZGl2aWR1YWwKdHJhbnMyPC10cmFucyAlPiUgZ3JvdXBfYnkoZGVjaW1hbExhdGl0dWRlLCBkZWNpbWFsTG9uZ2l0dWRlKSAlPiUgc3VtbWFyaXplKGluZGl2aWR1YWxDb3VudD1zdW0oaW5kaXZpZHVhbENvdW50LG5hLnJtID0gVCkpIAoKI2J5IHNwZWNpZXMKdHJhbnMzIDwtIHRyYW5zICU+JSBncm91cF9ieShzY2llbnRpZmljTmFtZSwgZGVjaW1hbExhdGl0dWRlLCBkZWNpbWFsTG9uZ2l0dWRlKSAlPiUgc3VtbWFyaXplKGNvdW50PW4oKSwgaW5kaXZpZHVhbENvdW50PXN1bShpbmRpdmlkdWFsQ291bnQsbmEucm09VCkpCgojcmljaG5lc3MKdHJhbnM0PC10cmFuczMgJT4lIGdyb3VwX2J5KGRlY2ltYWxMYXRpdHVkZSxkZWNpbWFsTG9uZ2l0dWRlKSAlPiUgc3VtbWFyaXplKHJpY2huZXNzPW4oKSkKCnRyYW5zNTwtbGVmdF9qb2luKHRyYW5zMix0cmFuczQpCgoKCgp0cmFuc19tYXA8LWdnbWFwKGRtYXApICsgZ2VvbV9wb2ludChkYXRhID0gdHJhbnM1LCBtYXBwaW5nID0gYWVzKHggPSBkZWNpbWFsTG9uZ2l0dWRlLCB5ID0gZGVjaW1hbExhdGl0dWRlLCBzaXplPWluZGl2aWR1YWxDb3VudCwgY29sb3I9cmljaG5lc3MpKSArIHNjYWxlX2NvbG9yX2dyYWRpZW50KGxvdyA9ICJncmVlbiIsIGhpZ2g9InJlZCIpICsgZ3VpZGVzKGNvbG9yPWd1aWRlX2NvbG9yYmFyKHRpdGxlPSJTcGVjaWVzIFJpY2huZXNzIiwpLCBzaXplPWd1aWRlX2xlZ2VuZCh0aXRsZT0iSW5kaXZpZHVhbCBDb3VudCIpKSArIHRoZW1lKGF4aXMudGl0bGU9ZWxlbWVudF9ibGFuaygpKSAKCnRyYW5zX21hcAoKZ2dzYXZlKHRyYW5zX21hcCxmaWxlbmFtZT0iLi9vdXRwdXQvdHJhbnNfbWFwLnBkZiIpCmBgYAoKIyBGaW5hbCBEYXRhYmFzZQoKTm93IHRvIGpvaW4gZXZlcnl0aGluZyBpbnRvIG9uZSBtb25zdGVyIGRhdGFiYXNlCgpgYGB7cn0KYTwtZnVsbF9qb2luKGZpc2gsYWxnYWUpCmI8LWZ1bGxfam9pbihhLGludmVydCkKYzwtZnVsbF9qb2luKGIsbWVpbykKZDwtZnVsbF9qb2luKGMsYXJtcykKTWFyaW5lR0VPSEk8LWZ1bGxfam9pbihkLHRyYW5zKQoKI3JlYWQgaW4gdGhlIGZsYXQgc2NoZW1hCmZsYXRfc2NoZW1hPC1hcy52ZWN0b3IocmVhZC5jc3YoImZsYXRfc2NoZW1hLmNzdiIsIGhlYWRlcj1GLCBzdHJpbmdzQXNGYWN0b3JzID0gRikpCgojcmVkdWNlIHRoZSBqb2luZWQgZGF0YWJhc2UgdG8ganVzdCB0aGUgY29sdW1ucyBpbiB0aGUgc2NoZW1hLCBhbmQgc29ydCBvbiBjb2x1bW4gb3JkZXIKTWFyaW5lR0VPSEkyPC1NYXJpbmVHRU9ISVssbWF0Y2goZmxhdF9zY2hlbWEsIG5hbWVzKE1hcmluZUdFT0hJKSldCgp3cml0ZS5jc3YoTWFyaW5lR0VPSEkyLCIuL291dHB1dC9NYXJpbmVHRU9ISV9kYXRhXzEuMS5jc3YiLHJvdy5uYW1lcyA9IEYpCgojV3JpdGVYTFMoYyhNYXJpbmVHRU9ISTIsYXMuZGF0YS5mcmFtZShldmVudHMpKSxFeGNlbEZpbGVOYW1lID0gIi4vb3V0cHV0L01hcmluZUdFT0hJX2RhdGFfMS4xLnhsc3giLFNoZWV0TmFtZXM9YygiRXZlbnRzIiwiU2FtcGxlcyIpKQoKYGBg